diff --git a/.github/workflows/automerge.yml b/.github/workflows/automerge.yml index 15efdef..1650f33 100644 --- a/.github/workflows/automerge.yml +++ b/.github/workflows/automerge.yml @@ -12,6 +12,6 @@ jobs: if: ${{ github.actor == 'dependabot[bot]' }} steps: - name: Merge non major updates - uses: trakx/github-actions/dependabot-automerge@v10.0.14 + uses: trakx/github-actions/dependabot-automerge@v10.0.26 with: githubToken: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/nuget.yml b/.github/workflows/nuget.yml index bbb7b3b..49f46e6 100644 --- a/.github/workflows/nuget.yml +++ b/.github/workflows/nuget.yml @@ -57,7 +57,7 @@ jobs: - name: Build and publish nuget packages id: publish - uses: trakx/github-actions/publish-nuget@v10.0.14 + uses: trakx/github-actions/publish-nuget@v10.0.26 with: packageReadonlyPat: ${{secrets.TRAKX_BOT_READONLY_PAT}} githubToken: ${{secrets.GITHUB_TOKEN}} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6117f96..67de735 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -14,7 +14,7 @@ jobs: steps: - name: Test and cover solutions id: test - uses: trakx/github-actions/test-dotnet@v10.0.14 + uses: trakx/github-actions/test-dotnet@v10.0.26 with: packageReadonlyPat: ${{secrets.TRAKX_BOT_READONLY_PAT}} codacyToken: ${{secrets.CODACY_TOKEN}} diff --git a/src/Trakx.CryptoCompare.ApiClient.Tests/Integration/Rest/Clients/PriceClientTests.cs b/src/Trakx.CryptoCompare.ApiClient.Tests/Integration/Rest/Clients/PriceClientTests.cs index fe6d3ef..d75cb60 100644 --- a/src/Trakx.CryptoCompare.ApiClient.Tests/Integration/Rest/Clients/PriceClientTests.cs +++ b/src/Trakx.CryptoCompare.ApiClient.Tests/Integration/Rest/Clients/PriceClientTests.cs @@ -1,4 +1,6 @@ -using System.Threading.Tasks; +using System; +using System.Linq; +using System.Threading.Tasks; using FluentAssertions; using Xunit; @@ -38,7 +40,8 @@ public async Task CanCallGenerateCustomAverageEndpoint() Assert.NotNull(result); } - [Fact] public async Task CanCallWithLargeNumberOfFSymbols() + [Fact] + public async Task CanCallWithLargeNumberOfFSymbols() { var symbols = new[] { @@ -50,8 +53,13 @@ [Fact] public async Task CanCallWithLargeNumberOfFSymbols() "srm", "cake", "luna" }; var result = await CryptoCompareClient.Prices.MultipleSymbolsPriceAsync(symbols, new[] { "USD", "EUR" }); - result.Count.Should().Be(symbols.Length); - Assert.NotNull(result); + + result.Should().NotBeEmpty(); + + var missingKeys = symbols.Except(result.Keys, StringComparer.OrdinalIgnoreCase).Order().ToList(); + + var maximumMissingAllowed = symbols.Length * 10 / 100; // 10% missing + missingKeys.Count.Should().BeLessThanOrEqualTo(maximumMissingAllowed); } } } diff --git a/src/Trakx.CryptoCompare.ApiClient.Tests/Trakx.CryptoCompare.ApiClient.Tests.csproj b/src/Trakx.CryptoCompare.ApiClient.Tests/Trakx.CryptoCompare.ApiClient.Tests.csproj index 4e092f7..e169195 100644 --- a/src/Trakx.CryptoCompare.ApiClient.Tests/Trakx.CryptoCompare.ApiClient.Tests.csproj +++ b/src/Trakx.CryptoCompare.ApiClient.Tests/Trakx.CryptoCompare.ApiClient.Tests.csproj @@ -16,17 +16,17 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Trakx.CryptoCompare.ApiClient.Tests/Unit/Rest/Helpers/CheckTest.cs b/src/Trakx.CryptoCompare.ApiClient.Tests/Unit/Rest/Helpers/CheckTest.cs index 34678c4..aa216b1 100644 --- a/src/Trakx.CryptoCompare.ApiClient.Tests/Unit/Rest/Helpers/CheckTest.cs +++ b/src/Trakx.CryptoCompare.ApiClient.Tests/Unit/Rest/Helpers/CheckTest.cs @@ -1,4 +1,5 @@ using System; +using FluentAssertions; using Trakx.CryptoCompare.ApiClient.Rest.Helpers; using Xunit; @@ -6,7 +7,7 @@ namespace Trakx.CryptoCompare.ApiClient.Tests.Unit.Rest.Helpers { public class CheckTest { - public static string Blah = nameof(Blah); + internal const string Blah = nameof(Blah); /// /// NotNullOrWhiteSpace should not throw ArgumentNullException when string is not null. @@ -27,7 +28,7 @@ public void NotNullOrWhiteSpaceShouldNotThrowArgumentNullExceptionWhenStringIsNo public void NotNullOrWhiteSpaceShouldThrowArgumentNullExceptionWhenStringIsNullOrEmptyOrWhitespace(string value) { var exception = Assert.Throws(() => Check.NotNullOrWhiteSpace(value, Blah)); - Assert.Equal(exception.ParamName, Blah); + exception.ParamName.Should().Be(Blah); } /// @@ -46,7 +47,7 @@ public void NotNullShouldNotThrowArgumentNullExceptionWhenObjectIsNotNull() public void NotNullShouldThrowArgumentNullExceptionWhenObjectIsNull() { var exception = Assert.Throws(() => Check.NotNull(null, Blah)); - Assert.Equal(exception.ParamName, Blah); + exception.ParamName.Should().Be(Blah); } } } diff --git a/src/Trakx.CryptoCompare.ApiClient.Tests/Unit/ServiceConfigurationTests.cs b/src/Trakx.CryptoCompare.ApiClient.Tests/Unit/ServiceConfigurationTests.cs index be502e9..d279d6e 100644 --- a/src/Trakx.CryptoCompare.ApiClient.Tests/Unit/ServiceConfigurationTests.cs +++ b/src/Trakx.CryptoCompare.ApiClient.Tests/Unit/ServiceConfigurationTests.cs @@ -1,4 +1,5 @@ -using Microsoft.Extensions.DependencyInjection; +using FluentAssertions; +using Microsoft.Extensions.DependencyInjection; using Xunit; namespace Trakx.CryptoCompare.ApiClient.Tests.Unit @@ -13,7 +14,10 @@ public void Services_should_be_built() var serviceCollection = new ServiceCollection(); serviceCollection.AddCryptoCompareClient(configuration); serviceCollection.AddLogging(); - var serviceProvider = serviceCollection.BuildServiceProvider(); + + var action = () => _ = serviceCollection.BuildServiceProvider(); + + action.Should().NotThrow(); } } } diff --git a/src/Trakx.CryptoCompare.ApiClient.Websocket.Tests/Integration/CryptoCompareWebsocketHandlerTests.cs b/src/Trakx.CryptoCompare.ApiClient.Websocket.Tests/Integration/CryptoCompareWebsocketHandlerTests.cs index 8dcfd10..143d798 100644 --- a/src/Trakx.CryptoCompare.ApiClient.Websocket.Tests/Integration/CryptoCompareWebsocketHandlerTests.cs +++ b/src/Trakx.CryptoCompare.ApiClient.Websocket.Tests/Integration/CryptoCompareWebsocketHandlerTests.cs @@ -1,5 +1,4 @@ using System; -using System.Globalization; using System.Linq; using System.Reactive.Linq; using System.Reactive.Threading.Tasks; @@ -40,12 +39,6 @@ public static IServiceProvider CreateServiceProvider() return serviceCollection.BuildServiceProvider(); } - public void Dispose() - { - _serviceScope.Dispose(); - } - - private async Task GetResult(string subStr, int bufferSeconds = 10) where T : InboundMessageBase { @@ -66,10 +59,9 @@ private async Task GetResult(string subStr, int bufferSeconds = 10) public async Task Should_be_able_to_get_full_top_tier_volume_subscriptions() { var subscriptionString = CryptoCompareSubscriptionFactory.GetFullTopTierVolumeSubscriptionStr("btc"); - var result = await GetResult(subscriptionString).ConfigureAwait(false); + var result = await GetResult(subscriptionString); result!.Symbol.Should().Be("BTC"); - decimal.TryParse(result.Volume, CultureInfo.InvariantCulture, out decimal volume); - volume.Should().BeGreaterThan(0); + result.Volume.Should().BeGreaterThan(0); } [Fact] @@ -87,11 +79,35 @@ public async Task Should_be_able_to_get_oc_book() public async Task Should_be_able_to_get_ohlcc_candles() { var subscriptionString = CryptoCompareSubscriptionFactory.GetOHLCCandlesSubscriptionStr("Binance", "btc", "usdt", "m"); - var result = await GetResult(subscriptionString).ConfigureAwait(false); + var result = await GetResult(subscriptionString); result!.Open.Should().BeGreaterThan(0); result!.LastTimeStamp.Should().BeGreaterThan(0); result!.Market.Should().NotBeNull(); result.Close.Should().BeGreaterThan(0); } + + #region IDisposable + + private bool _wasDisposed; + + protected virtual bool Dispose(bool disposing) + { + if (_wasDisposed) return false; + if (disposing) + { + _serviceScope.Dispose(); + } + + _wasDisposed = true; + return true; + } + + public void Dispose() + { + Dispose(disposing: true); + GC.SuppressFinalize(this); + } + + #endregion } } diff --git a/src/Trakx.CryptoCompare.ApiClient.Websocket.Tests/Trakx.CryptoCompare.ApiClient.Websocket.Tests.csproj b/src/Trakx.CryptoCompare.ApiClient.Websocket.Tests/Trakx.CryptoCompare.ApiClient.Websocket.Tests.csproj index 3dcda7f..e6d0fb2 100644 --- a/src/Trakx.CryptoCompare.ApiClient.Websocket.Tests/Trakx.CryptoCompare.ApiClient.Websocket.Tests.csproj +++ b/src/Trakx.CryptoCompare.ApiClient.Websocket.Tests/Trakx.CryptoCompare.ApiClient.Websocket.Tests.csproj @@ -18,18 +18,18 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + diff --git a/src/Trakx.CryptoCompare.ApiClient.Websocket/Extensions/AddCryptoCompareWebsocketsExtensions.cs b/src/Trakx.CryptoCompare.ApiClient.Websocket/Extensions/AddCryptoCompareWebsocketsExtensions.cs index b2c0948..f35777a 100644 --- a/src/Trakx.CryptoCompare.ApiClient.Websocket/Extensions/AddCryptoCompareWebsocketsExtensions.cs +++ b/src/Trakx.CryptoCompare.ApiClient.Websocket/Extensions/AddCryptoCompareWebsocketsExtensions.cs @@ -1,5 +1,6 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using Trakx.Common.Configuration; using Trakx.Websocket; using Trakx.Websocket.Interfaces; using Trakx.Websocket.Model; @@ -8,7 +9,10 @@ namespace Trakx.CryptoCompare.ApiClient.Websocket.Extensions; public static class AddCryptoCompareWebsocketsExtensions { - public static void AddCryptoCompareWebsockets(this IServiceCollection services, CryptoCompareApiConfiguration apiConfiguration, WebsocketConfiguration webSocketConfiguration) + public static void AddCryptoCompareWebsockets( + this IServiceCollection services, + CryptoCompareApiConfiguration apiConfiguration, + WebsocketConfiguration webSocketConfiguration) { services.AddSingleton(); services.AddSingleton(); @@ -18,10 +22,8 @@ public static void AddCryptoCompareWebsockets(this IServiceCollection services, public static void AddCryptoCompareWebsockets(this IServiceCollection services, IConfiguration config) { - var apiConfiguration = config.GetSection(nameof(CryptoCompareApiConfiguration)) - .Get(); - var webSocketConfig = config.GetSection(nameof(WebsocketConfiguration)).Get(); - + var apiConfiguration = config.GetConfiguration(); + var webSocketConfig = config.GetConfiguration(); AddCryptoCompareWebsockets(services, apiConfiguration, webSocketConfig); } } diff --git a/src/Trakx.CryptoCompare.ApiClient.Websocket/Model/HeartBeat.cs b/src/Trakx.CryptoCompare.ApiClient.Websocket/Model/HeartBeat.cs index df43081..a9cf0ed 100644 --- a/src/Trakx.CryptoCompare.ApiClient.Websocket/Model/HeartBeat.cs +++ b/src/Trakx.CryptoCompare.ApiClient.Websocket/Model/HeartBeat.cs @@ -4,6 +4,6 @@ namespace Trakx.CryptoCompare.ApiClient.Websocket.Model; public class HeartBeat : InboundMessageBase { - [JsonPropertyName("MESSAGE")] public string Message { get; set; } - [JsonPropertyName("TIMEMS")] public ulong TimeMs { get; set; } + [JsonPropertyName("MESSAGE")] public string? Message { get; set; } + [JsonPropertyName("TIMEMS")] public ulong? TimeMs { get; set; } } diff --git a/src/Trakx.CryptoCompare.ApiClient.Websocket/Model/InboundMessageBase.cs b/src/Trakx.CryptoCompare.ApiClient.Websocket/Model/InboundMessageBase.cs index aff0957..cd7c2d5 100644 --- a/src/Trakx.CryptoCompare.ApiClient.Websocket/Model/InboundMessageBase.cs +++ b/src/Trakx.CryptoCompare.ApiClient.Websocket/Model/InboundMessageBase.cs @@ -4,5 +4,5 @@ namespace Trakx.CryptoCompare.ApiClient.Websocket.Model; public class InboundMessageBase { - [JsonPropertyName("TYPE")] public string Type { get; set; } + [JsonPropertyName("TYPE")] public string? Type { get; set; } } diff --git a/src/Trakx.CryptoCompare.ApiClient.Websocket/Model/Ohlc.cs b/src/Trakx.CryptoCompare.ApiClient.Websocket/Model/Ohlc.cs index 8d94a17..83ce008 100644 --- a/src/Trakx.CryptoCompare.ApiClient.Websocket/Model/Ohlc.cs +++ b/src/Trakx.CryptoCompare.ApiClient.Websocket/Model/Ohlc.cs @@ -1,5 +1,5 @@ using System.Text.Json.Serialization; -using Trakx.Common.Serialization.Converters; +using Trakx.Common.Serialization.Comparers; namespace Trakx.CryptoCompare.ApiClient.Websocket.Model; diff --git a/src/Trakx.CryptoCompare.ApiClient.Websocket/Model/Ticker.cs b/src/Trakx.CryptoCompare.ApiClient.Websocket/Model/Ticker.cs index dec6b3f..5697406 100644 --- a/src/Trakx.CryptoCompare.ApiClient.Websocket/Model/Ticker.cs +++ b/src/Trakx.CryptoCompare.ApiClient.Websocket/Model/Ticker.cs @@ -1,14 +1,13 @@ using System.Text.Json.Serialization; -using Trakx.Common.Serialization.Converters; +using Trakx.Common.Serialization.Comparers; namespace Trakx.CryptoCompare.ApiClient.Websocket.Model; public class Ticker : InboundMessageBase { -#nullable disable - [JsonPropertyName("MARKET")] public string Market { get; set; } - [JsonPropertyName("FROMSYMBOL")] public string BaseSymbol { get; set; } - [JsonPropertyName("TOSYMBOL")] public string QuoteSymbol { get; set; } + [JsonPropertyName("MARKET")] public string? Market { get; set; } + [JsonPropertyName("FROMSYMBOL")] public string? BaseSymbol { get; set; } + [JsonPropertyName("TOSYMBOL")] public string? QuoteSymbol { get; set; } [JsonPropertyName("FLAGS"), JsonConverter(typeof(ULongOrStringConverter))] public ulong Flags { get; set; } @@ -33,5 +32,4 @@ public class Ticker : InboundMessageBase [JsonPropertyName("OPENHOUR")] public decimal? OpenHour { get; set; } [JsonPropertyName("HIGHHOUR")] public decimal? HighHour { get; set; } [JsonPropertyName("LOWHOUR")] public decimal? LowHour { get; set; } -#nullable restore } diff --git a/src/Trakx.CryptoCompare.ApiClient.Websocket/Model/TopTierFullVolume.cs b/src/Trakx.CryptoCompare.ApiClient.Websocket/Model/TopTierFullVolume.cs index 4dec8db..d15b6be 100644 --- a/src/Trakx.CryptoCompare.ApiClient.Websocket/Model/TopTierFullVolume.cs +++ b/src/Trakx.CryptoCompare.ApiClient.Websocket/Model/TopTierFullVolume.cs @@ -4,8 +4,9 @@ namespace Trakx.CryptoCompare.ApiClient.Websocket.Model; public class TopTierFullVolume : InboundMessageBase { -#nullable disable - [JsonPropertyName("SYMBOL")] public string Symbol { get; set; } - [JsonPropertyName("TOPTIERFULLVOLUME")] public string Volume { get; set; } -#nullable restore + [JsonPropertyName("SYMBOL")] + public string Symbol { get; set; } = default!; + + [JsonPropertyName("TOPTIERFULLVOLUME")] + public decimal Volume { get; set; } } diff --git a/src/Trakx.CryptoCompare.ApiClient.Websocket/Model/Trade.cs b/src/Trakx.CryptoCompare.ApiClient.Websocket/Model/Trade.cs index 28963a2..8afede3 100644 --- a/src/Trakx.CryptoCompare.ApiClient.Websocket/Model/Trade.cs +++ b/src/Trakx.CryptoCompare.ApiClient.Websocket/Model/Trade.cs @@ -1,5 +1,5 @@ using System.Text.Json.Serialization; -using Trakx.Common.Serialization.Converters; +using Trakx.Common.Serialization.Comparers; namespace Trakx.CryptoCompare.ApiClient.Websocket.Model; diff --git a/src/Trakx.CryptoCompare.ApiClient.Websocket/Trakx.CryptoCompare.ApiClient.Websocket.csproj b/src/Trakx.CryptoCompare.ApiClient.Websocket/Trakx.CryptoCompare.ApiClient.Websocket.csproj index edfae1b..4a085e1 100644 --- a/src/Trakx.CryptoCompare.ApiClient.Websocket/Trakx.CryptoCompare.ApiClient.Websocket.csproj +++ b/src/Trakx.CryptoCompare.ApiClient.Websocket/Trakx.CryptoCompare.ApiClient.Websocket.csproj @@ -1,19 +1,20 @@  - - net7.0 - + + net7.0 + - - + + - - - - + + + + + - - - + + + diff --git a/src/Trakx.CryptoCompare.ApiClient.sln b/src/Trakx.CryptoCompare.ApiClient.sln index fa6ad03..440779b 100644 --- a/src/Trakx.CryptoCompare.ApiClient.sln +++ b/src/Trakx.CryptoCompare.ApiClient.sln @@ -20,24 +20,21 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SolutionItems", "SolutionIt ..\README.md = ..\README.md EndProjectSection EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".github", ".github", "{6016A446-EAD5-451B-B8C0-EC13794036FB}" - ProjectSection(SolutionItems) = preProject - ..\.github\dependabot.yml = ..\.github\dependabot.yml - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{C1DFC2BD-A633-4692-9196-EBF451A87AE0}" - ProjectSection(SolutionItems) = preProject - ..\.github\workflows\dotnet-core.yml = ..\.github\workflows\dotnet-core.yml - ..\.github\workflows\publish.nuget.yml = ..\.github\workflows\publish.nuget.yml - EndProjectSection -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Trakx.CryptoCompare.ApiClient", "Trakx.CryptoCompare.ApiClient\Trakx.CryptoCompare.ApiClient.csproj", "{F43EBF54-E0AA-40D4-85AE-BBC8D06825AC}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Trakx.CryptoCompare.ApiClient.Tests", "Trakx.CryptoCompare.ApiClient.Tests\Trakx.CryptoCompare.ApiClient.Tests.csproj", "{D370556E-337B-4021-B954-71CE9AD1BCF8}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Trakx.CryptoCompare.ApiClient.Websocket", "Trakx.CryptoCompare.ApiClient.Websocket\Trakx.CryptoCompare.ApiClient.Websocket.csproj", "{A0FD368B-F4F2-4E0D-87A2-4866900156CE}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Trakx.CryptoCompare.ApiClient.Websocket", "Trakx.CryptoCompare.ApiClient.Websocket\Trakx.CryptoCompare.ApiClient.Websocket.csproj", "{A0FD368B-F4F2-4E0D-87A2-4866900156CE}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Trakx.CryptoCompare.ApiClient.Websocket.Tests", "Trakx.CryptoCompare.ApiClient.Websocket.Tests\Trakx.CryptoCompare.ApiClient.Websocket.Tests.csproj", "{4D9E5B67-4B53-4A40-BFFD-5FB07727E0EF}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Trakx.CryptoCompare.ApiClient.Websocket.Tests", "Trakx.CryptoCompare.ApiClient.Websocket.Tests\Trakx.CryptoCompare.ApiClient.Websocket.Tests.csproj", "{4D9E5B67-4B53-4A40-BFFD-5FB07727E0EF}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C37319D5-EA5F-404D-8BB2-07902D8C1D72}" + ProjectSection(SolutionItems) = preProject + ..\.github\workflows\automerge.yml = ..\.github\workflows\automerge.yml + ..\.github\workflows\delete.packages.yml = ..\.github\workflows\delete.packages.yml + ..\.github\workflows\nuget.yml = ..\.github\workflows\nuget.yml + ..\.github\workflows\test.yml = ..\.github\workflows\test.yml + EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -65,10 +62,6 @@ Global GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {6016A446-EAD5-451B-B8C0-EC13794036FB} = {B4B8ECDB-63A4-431A-8313-2D90142033C1} - {C1DFC2BD-A633-4692-9196-EBF451A87AE0} = {6016A446-EAD5-451B-B8C0-EC13794036FB} - EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {3F131DCD-33E4-47BA-8829-65E49F744112} EndGlobalSection diff --git a/src/Trakx.CryptoCompare.ApiClient/Rest/Clients/BaseApiClient.cs b/src/Trakx.CryptoCompare.ApiClient/Rest/Clients/BaseApiClient.cs index 9ccceca..b291b3e 100644 --- a/src/Trakx.CryptoCompare.ApiClient/Rest/Clients/BaseApiClient.cs +++ b/src/Trakx.CryptoCompare.ApiClient/Rest/Clients/BaseApiClient.cs @@ -63,18 +63,17 @@ public async Task SendRequestAsync(HttpMethod httpMe { var apiResponseObject = JsonConvert.DeserializeObject(jsonResponse); - var baseApiResponse = apiResponseObject as BaseApiResponse; - if (baseApiResponse != null && !baseApiResponse.IsSuccessfulResponse) + if (apiResponseObject is BaseApiResponse baseApiResponse && !baseApiResponse.IsSuccessfulResponse) { throw new CryptoCompareException(baseApiResponse); } - return apiResponseObject; + return apiResponseObject!; } catch (JsonSerializationException jsonSerializationException) { var apiErrorResponse = JsonConvert.DeserializeObject(jsonResponse); - throw new CryptoCompareException(apiErrorResponse, jsonSerializationException); + throw new CryptoCompareException(apiErrorResponse!, jsonSerializationException); } } } diff --git a/src/Trakx.CryptoCompare.ApiClient/Rest/Clients/HistoryClient.cs b/src/Trakx.CryptoCompare.ApiClient/Rest/Clients/HistoryClient.cs index 26e784d..5c833f3 100644 --- a/src/Trakx.CryptoCompare.ApiClient/Rest/Clients/HistoryClient.cs +++ b/src/Trakx.CryptoCompare.ApiClient/Rest/Clients/HistoryClient.cs @@ -16,7 +16,7 @@ public HistoryClient(HttpClient httpClient) { Check.NotNull(httpClient, nameof(httpClient)); } - + /// /// Get the price of any cryptocurrency in any other currency that you need at a given timestamp. /// The price comes from the daily info - so it would be the price at the end of the day GMT based on the requested TS. @@ -42,7 +42,6 @@ public async Task HistoricalForTimestampAsync( { Check.NotNullOrWhiteSpace(fromSymbol, nameof(fromSymbol)); Check.NotEmpty(toSymbols, nameof(toSymbols)); - return await this.GetAsync( ApiUrls.PriceHistorical( @@ -53,7 +52,7 @@ public async Task HistoricalForTimestampAsync( calculationType, tryConversion)).ConfigureAwait(false); } - + /// /// Get open, high, low, close, volumefrom and volumeto from the daily historical data. /// The values are based on 00:00 GMT time.It uses BTC conversion if data is not available because the coin is not trading in the specified currency. @@ -69,7 +68,7 @@ public async Task HistoricalForTimestampAsync( public async Task DailyAsync( string fromSymbol, string toSymbol, - int? limit = null, + int? limit, string? exchangeName = null, DateTimeOffset? toDate = null, bool? allData = null, diff --git a/src/Trakx.CryptoCompare.ApiClient/Rest/Clients/IHistoryClient.cs b/src/Trakx.CryptoCompare.ApiClient/Rest/Clients/IHistoryClient.cs index 3f0c21c..b7cee0e 100644 --- a/src/Trakx.CryptoCompare.ApiClient/Rest/Clients/IHistoryClient.cs +++ b/src/Trakx.CryptoCompare.ApiClient/Rest/Clients/IHistoryClient.cs @@ -26,7 +26,7 @@ Task HistoricalForTimestampAsync( string fromSymbol, IEnumerable toSymbols, DateTimeOffset requestedDate, - IEnumerable markets = null, + IEnumerable? markets = null, CalculationType? calculationType = null, bool? tryConversion = null); @@ -46,7 +46,7 @@ Task DailyAsync( [NotNull] string fromSymbol, [NotNull] string toSymbol, int? limit, - string exchangeName = null, + string? exchangeName = null, DateTimeOffset? toDate = null, bool? allData = null, int? aggregate = null, @@ -68,7 +68,7 @@ Task HourlyAsync( [NotNull] string fromSymbol, [NotNull] string toSymbol, int? limit = null, - string exchangeName = null, + string? exchangeName = null, DateTimeOffset? toDate = null, bool? allData = null, int? aggregate = null, @@ -91,7 +91,7 @@ Task MinutelyAsync( [NotNull] string fromSymbol, [NotNull] string toSymbol, int? limit = null, - string exchangeName = null, + string? exchangeName = null, DateTimeOffset? toDate = null, bool? allData = null, int? aggregate = null, @@ -114,7 +114,7 @@ Task MinutelyAsync( Task DayAveragePriceAsync( [NotNull] string fromSymbol, [NotNull] string toSymbol, - string exchangeName = null, + string? exchangeName = null, DateTimeOffset? toDate = null, CalculationType? avgType = null, int? utcHourDiff = null, @@ -134,7 +134,7 @@ Task DayAveragePriceAsync( /// Task ExchangeDailyAsync( [NotNull] string toSymbol, - string exchangeName = null, + string? exchangeName = null, DateTimeOffset? toDate = null, int? limit = null, int? aggregate = null, @@ -154,7 +154,7 @@ Task ExchangeDailyAsync( /// Task ExchangeHourlyAsync( [NotNull] string toSymbol, - string exchangeName = null, + string? exchangeName = null, DateTimeOffset? toDate = null, int? limit = null, int? aggregate = null, diff --git a/src/Trakx.CryptoCompare.ApiClient/Rest/Clients/INewsClient.cs b/src/Trakx.CryptoCompare.ApiClient/Rest/Clients/INewsClient.cs index 1b18172..6a8bb92 100644 --- a/src/Trakx.CryptoCompare.ApiClient/Rest/Clients/INewsClient.cs +++ b/src/Trakx.CryptoCompare.ApiClient/Rest/Clients/INewsClient.cs @@ -6,11 +6,11 @@ namespace Trakx.CryptoCompare.ApiClient.Rest.Clients { public interface INewsClient { - /// - /// Return all news providers. - /// - /// - Task> NewsProviders(); + /// + /// Return all news providers. + /// + /// + Task> NewsProviders(); /// /// Get all news /// @@ -19,7 +19,7 @@ public interface INewsClient /// Feeds - for news /// if true cryptocompare will sign request /// - Task> News(string lang = null, long? lTs = null, string[] feeds = null, + Task> News(string? lang = null, long? lTs = null, string[]? feeds = null, bool? sign = null); } diff --git a/src/Trakx.CryptoCompare.ApiClient/Rest/Clients/IPricesClient.cs b/src/Trakx.CryptoCompare.ApiClient/Rest/Clients/IPricesClient.cs index 4a2560e..f1fe6d2 100644 --- a/src/Trakx.CryptoCompare.ApiClient/Rest/Clients/IPricesClient.cs +++ b/src/Trakx.CryptoCompare.ApiClient/Rest/Clients/IPricesClient.cs @@ -32,7 +32,7 @@ Task MultipleSymbolsPriceAsync( IEnumerable fromSymbols, IEnumerable toSymbols, bool? tryConversion = null, - string exchangeName = null); + string? exchangeName = null); /// /// Get all the current trading info (price, vol, open, high, low etc) of any list of cryptocurrencies in any other currency that you need. @@ -49,7 +49,7 @@ Task MultipleSymbolFullDataAsync( IEnumerable fromSymbols, IEnumerable toSymbols, bool? tryConversion = null, - string exchangeName = null); + string? exchangeName = null); /// /// Get the current price of any cryptocurrency in any other currency that you need. @@ -64,6 +64,6 @@ Task SingleSymbolPriceAsync( string fromSymbol, IEnumerable toSymbols, bool? tryConversion = null, - string exchangeName = null); + string? exchangeName = null); } } diff --git a/src/Trakx.CryptoCompare.ApiClient/Rest/Clients/PriceClient.cs b/src/Trakx.CryptoCompare.ApiClient/Rest/Clients/PriceClient.cs index e6ba584..43288ec 100644 --- a/src/Trakx.CryptoCompare.ApiClient/Rest/Clients/PriceClient.cs +++ b/src/Trakx.CryptoCompare.ApiClient/Rest/Clients/PriceClient.cs @@ -150,7 +150,7 @@ public async Task SingleSymbolPriceAsync( [NotNull] string fromSymbol, [NotNull] IEnumerable toSymbols, bool? tryConversion = null, - string exchangeName = null) + string? exchangeName = null) { Check.NotNull(fromSymbol, nameof(fromSymbol)); Check.NotEmpty(toSymbols, nameof(toSymbols)); diff --git a/src/Trakx.CryptoCompare.ApiClient/Rest/Converters/StringToSubConverter.cs b/src/Trakx.CryptoCompare.ApiClient/Rest/Converters/StringToSubConverter.cs index 410a0b0..e748825 100644 --- a/src/Trakx.CryptoCompare.ApiClient/Rest/Converters/StringToSubConverter.cs +++ b/src/Trakx.CryptoCompare.ApiClient/Rest/Converters/StringToSubConverter.cs @@ -37,12 +37,12 @@ public override bool CanConvert(Type objectType) public override object ReadJson( JsonReader reader, Type objectType, - object existingValue, + object? existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.String) { - return this.GetTokenFromString(reader.Value.ToString()); + return GetTokenFromString(reader.Value?.ToString()); } if (reader.TokenType == JsonToken.StartArray) @@ -50,11 +50,11 @@ public override object ReadJson( var tokens = JArray.Load(reader); if (tokens?.HasValues ?? false) { - return tokens.Values().Select(token => this.GetTokenFromString(token.ToString())).ToList(); + return tokens.Values().Select(token => GetTokenFromString(token.ToString())).ToList(); } } - return null; + return null!; } /// @@ -64,13 +64,14 @@ public override object ReadJson( /// The value. /// The calling serializer. /// - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { throw new NotImplementedException(); } - private Sub GetTokenFromString(string token) + private static Sub GetTokenFromString(string? token) { + if (token == null) return default; var values = token.Split('~'); if (values.Length == 4) { @@ -81,7 +82,7 @@ private Sub GetTokenFromString(string token) subId, values.ElementAtOrDefault(3)); } - return default(Sub); + return default; } } } diff --git a/src/Trakx.CryptoCompare.ApiClient/Rest/Core/ApiUrls.cs b/src/Trakx.CryptoCompare.ApiClient/Rest/Core/ApiUrls.cs index 1314e33..f9dbde8 100644 --- a/src/Trakx.CryptoCompare.ApiClient/Rest/Core/ApiUrls.cs +++ b/src/Trakx.CryptoCompare.ApiClient/Rest/Core/ApiUrls.cs @@ -12,22 +12,22 @@ internal static class ApiUrls { private const string RateLimitsUrl = "/stats/rate/{0}/limit"; - public static readonly Uri MinApiEndpoint = new Uri( + public static readonly Uri MinApiEndpoint = new( "https://min-api.cryptocompare.com/data/", UriKind.Absolute); - public static readonly Uri SiteApiEndpoint = new Uri( + public static readonly Uri SiteApiEndpoint = new( "https://www.cryptocompare.com/api/data/", UriKind.Absolute); - public static Uri AllCoins() => new Uri(MinApiEndpoint, "all/coinlist"); + public static Uri AllCoins() => new(MinApiEndpoint, "all/coinlist"); - public static Uri AllExchanges() => new Uri(MinApiEndpoint, "all/exchanges"); + public static Uri AllExchanges() => new(MinApiEndpoint, "all/exchanges"); public static Uri DayAveragePrice( string fsym, string tsym, - string e, + string? e, DateTimeOffset? toTs, CalculationType? avgType, int? UTCHourDiff, @@ -97,9 +97,9 @@ public static Uri ExchangeHistory( }); } - public static Uri MiningContracts() => new Uri(SiteApiEndpoint, "miningcontracts"); + public static Uri MiningContracts() => new(SiteApiEndpoint, "miningcontracts"); - public static Uri MiningEquipments() => new Uri(SiteApiEndpoint, "miningequipment"); + public static Uri MiningEquipments() => new(SiteApiEndpoint, "miningequipment"); public static Uri News(string? lang = null, long? lTs = null, string[]? feeds = null, bool? sign = null) { @@ -141,7 +141,7 @@ public static Uri PriceAverage( public static Uri PriceHistorical( string fsym, IEnumerable tsyms, - IEnumerable markets, + IEnumerable? markets, DateTimeOffset ts, CalculationType? calculationType, bool? tryConversion) @@ -215,11 +215,11 @@ public static Uri PriceSingle( }); } - public static Uri RateLimitsByHour() => new Uri(MinApiEndpoint, string.Format(RateLimitsUrl, "hour")); + public static Uri RateLimitsByHour() => new(MinApiEndpoint, string.Format(RateLimitsUrl, "hour")); - public static Uri RateLimitsByMinute() => new Uri(MinApiEndpoint, string.Format(RateLimitsUrl, "minute")); + public static Uri RateLimitsByMinute() => new(MinApiEndpoint, string.Format(RateLimitsUrl, "minute")); - public static Uri RateLimitsBySecond() => new Uri(MinApiEndpoint, string.Format(RateLimitsUrl, "second")); + public static Uri RateLimitsBySecond() => new(MinApiEndpoint, string.Format(RateLimitsUrl, "second")); public static Uri SocialStats([NotNull] int id) { diff --git a/src/Trakx.CryptoCompare.ApiClient/Rest/Core/ThottledHttpClientHandler.cs b/src/Trakx.CryptoCompare.ApiClient/Rest/Core/ThottledHttpClientHandler.cs index d462edc..59d2a17 100644 --- a/src/Trakx.CryptoCompare.ApiClient/Rest/Core/ThottledHttpClientHandler.cs +++ b/src/Trakx.CryptoCompare.ApiClient/Rest/Core/ThottledHttpClientHandler.cs @@ -24,14 +24,14 @@ public ThottledHttpClientHandler(int millisecondsDelay) this._semaphore = new SemaphoreSlim(1, 1); } - protected override async Task SendAsync(HttpRequestMessage requestMessage, CancellationToken cancellationToken) + protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { - Check.NotNull(requestMessage, nameof(requestMessage)); + Check.NotNull(request, nameof(request)); await this._semaphore.WaitAsync(cancellationToken).ConfigureAwait(false); try { - return await base.SendAsync(requestMessage, cancellationToken); + return await base.SendAsync(request, cancellationToken); } finally { diff --git a/src/Trakx.CryptoCompare.ApiClient/Rest/Extensions/DateTimeExtensions.cs b/src/Trakx.CryptoCompare.ApiClient/Rest/Extensions/DateTimeExtensions.cs index 58cf5eb..b232c24 100644 --- a/src/Trakx.CryptoCompare.ApiClient/Rest/Extensions/DateTimeExtensions.cs +++ b/src/Trakx.CryptoCompare.ApiClient/Rest/Extensions/DateTimeExtensions.cs @@ -1,10 +1,11 @@ using System; +using Trakx.Common.Extensions; namespace Trakx.CryptoCompare.ApiClient.Rest.Extensions { public static class DateTimeExtensions { - private static readonly DateTimeOffset epoch = new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero); + private static readonly DateTimeOffset epoch = (1970, 1, 1).ToDateTimeOffset(); /// /// Convert a Unix tick to a with UTC offset diff --git a/src/Trakx.CryptoCompare.ApiClient/Rest/Extensions/UriExtensions.cs b/src/Trakx.CryptoCompare.ApiClient/Rest/Extensions/UriExtensions.cs index b1915cc..b83f8fd 100644 --- a/src/Trakx.CryptoCompare.ApiClient/Rest/Extensions/UriExtensions.cs +++ b/src/Trakx.CryptoCompare.ApiClient/Rest/Extensions/UriExtensions.cs @@ -33,7 +33,7 @@ public static Uri ApplyParameters([NotNull] this Uri uri, IDictionary key.Substring(0, key.IndexOf('=')), - value => value.Substring(value.IndexOf('=') + 1)); + key => key[..key.IndexOf('=')], + value => value[(value.IndexOf('=') + 1)..]); foreach (var (k, v) in existingParameters) { if (!p.ContainsKey(k)) { - p.Add(k,v); + p.Add(k, v); } } var query = string.Join( "&", p.Where(param => !string.IsNullOrWhiteSpace(param.Value)) - .Select(kvp => kvp.Key + "=" + Uri.EscapeDataString(kvp.Value))); + .Select(kvp => kvp.Key + "=" + Uri.EscapeDataString(kvp.Value!))); if (uri.IsAbsoluteUri) { var uriBuilder = new UriBuilder(uri) - { - Query = query - }; + { + Query = query + }; return uriBuilder.Uri; } diff --git a/src/Trakx.CryptoCompare.ApiClient/Rest/Helpers/Check.cs b/src/Trakx.CryptoCompare.ApiClient/Rest/Helpers/Check.cs index 1eae50b..18be666 100644 --- a/src/Trakx.CryptoCompare.ApiClient/Rest/Helpers/Check.cs +++ b/src/Trakx.CryptoCompare.ApiClient/Rest/Helpers/Check.cs @@ -23,7 +23,7 @@ internal static class Check [ContractAnnotation("value:null => halt")] public static IEnumerable NotEmpty( IEnumerable value, - [InvokerParameterName] [NotNull] string parameterName) + [InvokerParameterName][NotNull] string parameterName) { NotNull(value, parameterName); @@ -47,9 +47,9 @@ public static IEnumerable NotEmpty( /// Checked object. /// [ContractAnnotation("value:null => halt")] - public static T NotNull(T value, [InvokerParameterName] [NotNull] string parameterName) + public static T NotNull(T value, [InvokerParameterName][NotNull] string parameterName) { - if (ReferenceEquals(value, null)) + if (value is null) { NotNullOrWhiteSpace(parameterName, nameof(parameterName)); throw new ArgumentNullException(parameterName); @@ -67,7 +67,7 @@ public static T NotNull(T value, [InvokerParameterName] [NotNull] string para /// Checked object. /// [ContractAnnotation("value:null => halt")] - public static string NotNullOrWhiteSpace(string value, [InvokerParameterName] [NotNull] string parameterName) + public static string NotNullOrWhiteSpace(string? value, [InvokerParameterName][NotNull] string parameterName) { if (string.IsNullOrWhiteSpace(value)) { diff --git a/src/Trakx.CryptoCompare.ApiClient/Rest/Helpers/JetbrainsAnnotations.cs b/src/Trakx.CryptoCompare.ApiClient/Rest/Helpers/JetbrainsAnnotations.cs index 8f21d7a..2f35231 100644 --- a/src/Trakx.CryptoCompare.ApiClient/Rest/Helpers/JetbrainsAnnotations.cs +++ b/src/Trakx.CryptoCompare.ApiClient/Rest/Helpers/JetbrainsAnnotations.cs @@ -22,7 +22,6 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE using System; -#pragma warning disable 1591 // ReSharper disable UnusedMember.Global // ReSharper disable MemberCanBePrivate.Global // ReSharper disable UnusedAutoPropertyAccessor.Global @@ -134,7 +133,7 @@ public StringFormatMethodAttribute([NotNull] string formatParameterName) } [NotNull] - public string FormatParameterName { get; private set; } + public string? FormatParameterName { get; private set; } } /// @@ -150,7 +149,7 @@ public ValueProviderAttribute([NotNull] string name) } [NotNull] - public string Name { get; private set; } + public string? Name { get; private set; } } /// @@ -220,7 +219,7 @@ public NotifyPropertyChangedInvocatorAttribute([NotNull] string parameterName) } [CanBeNull] - public string ParameterName { get; private set; } + public string? ParameterName { get; private set; } } /// @@ -281,7 +280,7 @@ public ContractAnnotationAttribute([NotNull] string contract, bool forceFullStat } [NotNull] - public string Contract { get; private set; } + public string? Contract { get; private set; } public bool ForceFullStates { get; private set; } } @@ -368,29 +367,29 @@ public BaseTypeRequiredAttribute([NotNull] Type baseType) internal sealed class UsedImplicitlyAttribute : Attribute { public UsedImplicitlyAttribute() - : this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default) + : this(ImplicitUseKinds.Default, ImplicitUseTargets.Default) { } - public UsedImplicitlyAttribute(ImplicitUseKindFlags useKindFlags) - : this(useKindFlags, ImplicitUseTargetFlags.Default) + public UsedImplicitlyAttribute(ImplicitUseKinds useKindFlags) + : this(useKindFlags, ImplicitUseTargets.Default) { } - public UsedImplicitlyAttribute(ImplicitUseTargetFlags targetFlags) - : this(ImplicitUseKindFlags.Default, targetFlags) + public UsedImplicitlyAttribute(ImplicitUseTargets targetFlags) + : this(ImplicitUseKinds.Default, targetFlags) { } - public UsedImplicitlyAttribute(ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags) + public UsedImplicitlyAttribute(ImplicitUseKinds useKindFlags, ImplicitUseTargets targetFlags) { UseKindFlags = useKindFlags; TargetFlags = targetFlags; } - public ImplicitUseTargetFlags TargetFlags { get; private set; } + public ImplicitUseTargets TargetFlags { get; private set; } - public ImplicitUseKindFlags UseKindFlags { get; private set; } + public ImplicitUseKinds UseKindFlags { get; private set; } } /// @@ -401,35 +400,35 @@ public UsedImplicitlyAttribute(ImplicitUseKindFlags useKindFlags, ImplicitUseTar internal sealed class MeansImplicitUseAttribute : Attribute { public MeansImplicitUseAttribute() - : this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default) + : this(ImplicitUseKinds.Default, ImplicitUseTargets.Default) { } - public MeansImplicitUseAttribute(ImplicitUseKindFlags useKindFlags) - : this(useKindFlags, ImplicitUseTargetFlags.Default) + public MeansImplicitUseAttribute(ImplicitUseKinds useKindFlags) + : this(useKindFlags, ImplicitUseTargets.Default) { } - public MeansImplicitUseAttribute(ImplicitUseTargetFlags targetFlags) - : this(ImplicitUseKindFlags.Default, targetFlags) + public MeansImplicitUseAttribute(ImplicitUseTargets targetFlags) + : this(ImplicitUseKinds.Default, targetFlags) { } - public MeansImplicitUseAttribute(ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags) + public MeansImplicitUseAttribute(ImplicitUseKinds useKindFlags, ImplicitUseTargets targetFlags) { UseKindFlags = useKindFlags; TargetFlags = targetFlags; } [UsedImplicitly] - public ImplicitUseTargetFlags TargetFlags { get; private set; } + public ImplicitUseTargets TargetFlags { get; private set; } [UsedImplicitly] - public ImplicitUseKindFlags UseKindFlags { get; private set; } + public ImplicitUseKinds UseKindFlags { get; private set; } } [Flags] - internal enum ImplicitUseKindFlags + internal enum ImplicitUseKinds { Default = Access | Assign | InstantiatedWithFixedConstructorSignature, @@ -454,7 +453,7 @@ internal enum ImplicitUseKindFlags /// with or . /// [Flags] - internal enum ImplicitUseTargetFlags + internal enum ImplicitUseTargets { Default = Itself, @@ -471,20 +470,20 @@ internal enum ImplicitUseTargetFlags /// This attribute is intended to mark publicly available API /// which should not be removed and so is treated as used. /// - [MeansImplicitUse(ImplicitUseTargetFlags.WithMembers)] - internal sealed class PublicAPIAttribute : Attribute + [MeansImplicitUse(ImplicitUseTargets.WithMembers)] + internal sealed class PublicApiAttribute : Attribute { - public PublicAPIAttribute() + public PublicApiAttribute() { } - public PublicAPIAttribute([NotNull] string comment) + public PublicApiAttribute([NotNull] string comment) { Comment = comment; } [CanBeNull] - public string Comment { get; private set; } + public string? Comment { get; private set; } } /// @@ -529,7 +528,7 @@ public MustUseReturnValueAttribute([NotNull] string justification) } [CanBeNull] - public string Justification { get; private set; } + public string? Justification { get; private set; } } /// @@ -572,7 +571,7 @@ public PathReferenceAttribute([NotNull, PathReference] string basePath) } [CanBeNull] - public string BasePath { get; private set; } + public string? BasePath { get; private set; } } /// @@ -648,13 +647,13 @@ internal sealed class MacroAttribute : Attribute /// Allows specifying a macro that will be executed for a source template /// parameter when the template is expanded. /// - public string Expression { get; set; } + public string? Expression { get; set; } /// /// Identifies the target parameter of a source template if the /// is applied on a template method. /// - public string Target { get; set; } + public string? Target { get; set; } } [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] @@ -666,7 +665,7 @@ public AspMvcAreaMasterLocationFormatAttribute([NotNull] string format) } [NotNull] - public string Format { get; private set; } + public string? Format { get; private set; } } [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] @@ -678,7 +677,7 @@ public AspMvcAreaPartialViewLocationFormatAttribute([NotNull] string format) } [NotNull] - public string Format { get; private set; } + public string? Format { get; private set; } } [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] @@ -690,7 +689,7 @@ public AspMvcAreaViewLocationFormatAttribute([NotNull] string format) } [NotNull] - public string Format { get; private set; } + public string? Format { get; private set; } } [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] @@ -713,7 +712,7 @@ public AspMvcPartialViewLocationFormatAttribute([NotNull] string format) } [NotNull] - public string Format { get; private set; } + public string? Format { get; private set; } } [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] @@ -725,7 +724,7 @@ public AspMvcViewLocationFormatAttribute([NotNull] string format) } [NotNull] - public string Format { get; private set; } + public string? Format { get; private set; } } /// @@ -747,7 +746,7 @@ public AspMvcActionAttribute([NotNull] string anonymousProperty) } [CanBeNull] - public string AnonymousProperty { get; private set; } + public string? AnonymousProperty { get; private set; } } /// @@ -768,7 +767,7 @@ public AspMvcAreaAttribute([NotNull] string anonymousProperty) } [CanBeNull] - public string AnonymousProperty { get; private set; } + public string? AnonymousProperty { get; private set; } } /// @@ -790,7 +789,7 @@ public AspMvcControllerAttribute([NotNull] string anonymousProperty) } [CanBeNull] - public string AnonymousProperty { get; private set; } + public string? AnonymousProperty { get; private set; } } /// @@ -918,7 +917,7 @@ public HtmlElementAttributesAttribute([NotNull] string name) } [CanBeNull] - public string Name { get; private set; } + public string? Name { get; private set; } } [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] @@ -930,7 +929,7 @@ public HtmlAttributeValueAttribute([NotNull] string name) } [NotNull] - public string Name { get; private set; } + public string? Name { get; private set; } } /// @@ -1091,7 +1090,7 @@ public AspChildControlTypeAttribute([NotNull] string tagName, [NotNull] Type con public Type ControlType { get; private set; } [NotNull] - public string TagName { get; private set; } + public string? TagName { get; private set; } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Method)] @@ -1118,7 +1117,7 @@ public AspRequiredAttributeAttribute([NotNull] string attribute) } [NotNull] - public string Attribute { get; private set; } + public string? Attribute { get; private set; } } [AttributeUsage(AttributeTargets.Property)] @@ -1141,7 +1140,7 @@ public RazorImportNamespaceAttribute([NotNull] string name) } [NotNull] - public string Name { get; private set; } + public string? Name { get; private set; } } [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] @@ -1154,10 +1153,10 @@ public RazorInjectionAttribute([NotNull] string type, [NotNull] string fieldName } [NotNull] - public string FieldName { get; private set; } + public string? FieldName { get; private set; } [NotNull] - public string Type { get; private set; } + public string? Type { get; private set; } } [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] @@ -1169,7 +1168,7 @@ public RazorDirectiveAttribute([NotNull] string directive) } [NotNull] - public string Directive { get; private set; } + public string? Directive { get; private set; } } [AttributeUsage(AttributeTargets.Method)] @@ -1204,7 +1203,7 @@ internal sealed class RazorWriteMethodParameterAttribute : Attribute /// The attribute must be mentioned in your member reordering patterns /// [AttributeUsage(AttributeTargets.All)] - internal sealed class NoReorder : Attribute + internal sealed class NoReorderAttribute : Attribute { } } diff --git a/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/AggregatedData.cs b/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/AggregatedData.cs index 8f30f6e..c962733 100644 --- a/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/AggregatedData.cs +++ b/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/AggregatedData.cs @@ -7,16 +7,16 @@ namespace Trakx.CryptoCompare.ApiClient.Rest.Models.Responses public class AggregatedData { [JsonProperty("FLAGS")] - public string Flags { get; set; } + public string? Flags { get; set; } [JsonProperty("FROMSYMBOL")] - public string BaseSymbol { get; set; } + public string? BaseSymbol { get; set; } [JsonProperty("HIGH24HOUR")] public double? High24Hour { get; set; } [JsonProperty("LASTTRADEID")] - public string LastTradeId { get; set; } + public string? LastTradeId { get; set; } [JsonConverter(typeof(UnixTimeConverter))] [JsonProperty("LASTUPDATE")] @@ -32,7 +32,7 @@ public class AggregatedData public double? Low24Hour { get; set; } [JsonProperty("MARKET")] - public string Market { get; set; } + public string? Market { get; set; } [JsonProperty("OPEN24HOUR")] public double? Open24Hour { get; set; } @@ -41,10 +41,10 @@ public class AggregatedData public double? Price { get; set; } [JsonProperty("TOSYMBOL")] - public string QuoteSymbol { get; set; } + public string? QuoteSymbol { get; set; } [JsonProperty("TYPE")] - public string Type { get; set; } + public string? Type { get; set; } [JsonProperty("VOLUME24HOUR")] public double? Volume24Hour { get; set; } diff --git a/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/Calls.cs b/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/Calls.cs index bf23415..ff13a72 100644 --- a/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/Calls.cs +++ b/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/Calls.cs @@ -1,10 +1,9 @@ -#pragma warning disable 8618 -namespace Trakx.CryptoCompare.ApiClient.Rest.Models.Responses +namespace Trakx.CryptoCompare.ApiClient.Rest.Models.Responses { /// /// Api calls. /// -public class Calls + public class Calls { /// /// Calls to history apis. diff --git a/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/CoinAggregatedData.cs b/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/CoinAggregatedData.cs index d68ea2d..1524981 100644 --- a/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/CoinAggregatedData.cs +++ b/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/CoinAggregatedData.cs @@ -8,7 +8,7 @@ public class CoinAggregatedData : AggregatedData public double? HighDay { get; set; } [JsonProperty("LASTMARKET")] - public string LastMarket { get; set; } + public string? LastMarket { get; set; } [JsonProperty("LOWDAY")] public double? LowDay { get; set; } diff --git a/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/CoinSnapshotFullData.cs b/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/CoinSnapshotFullData.cs index 7d56314..03fa07e 100644 --- a/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/CoinSnapshotFullData.cs +++ b/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/CoinSnapshotFullData.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Collections.Immutable; using Newtonsoft.Json; using Trakx.CryptoCompare.ApiClient.Rest.Converters; @@ -6,15 +7,15 @@ namespace Trakx.CryptoCompare.ApiClient.Rest.Models.Responses { public class CoinSnapshotFullData { - public CoinGeneralInfo General { get; set; } + public CoinGeneralInfo? General { get; set; } - public ICO ICO { get; set; } + public Ico? ICO { get; set; } - public SEO SEO { get; set; } + public Seo? SEO { get; set; } - public IReadOnlyList StreamerDataRaw { get; set; } + public IReadOnlyList StreamerDataRaw { get; set; } = ImmutableList.Empty; [JsonConverter(typeof(StringToSubConverter))] - public IReadOnlyList Subs { get; set; } + public IReadOnlyList Subs { get; set; } = ImmutableList.Empty; } } diff --git a/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/CoinSnapshotFullResponse.cs b/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/CoinSnapshotFullResponse.cs index fa8c82d..7d70307 100644 --- a/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/CoinSnapshotFullResponse.cs +++ b/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/CoinSnapshotFullResponse.cs @@ -2,6 +2,6 @@ { public class CoinSnapshotFullResponse : BaseApiResponse { - public CoinSnapshotFullData Data { get; set; } + public CoinSnapshotFullData? Data { get; set; } } } diff --git a/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/ICO.cs b/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/ICO.cs index defbf68..5ab90a8 100644 --- a/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/ICO.cs +++ b/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/ICO.cs @@ -5,7 +5,7 @@ namespace Trakx.CryptoCompare.ApiClient.Rest.Models.Responses { - public class ICO + public class Ico { public string Blog { get; set; } diff --git a/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/MarketCapDisplay.cs b/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/MarketCapDisplay.cs index 482cd02..e890dd1 100644 --- a/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/MarketCapDisplay.cs +++ b/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/MarketCapDisplay.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System.Collections.ObjectModel; -#pragma warning disable 8618 namespace Trakx.CryptoCompare.ApiClient.Rest.Models.Responses { diff --git a/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/MiningEquipment.cs b/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/MiningEquipment.cs index 5d32286..e8ea8b5 100644 --- a/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/MiningEquipment.cs +++ b/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/MiningEquipment.cs @@ -2,8 +2,8 @@ { public class MiningEquipment : MiningData { - public string EquipmentType { get; set; } + public string? EquipmentType { get; set; } - public string PowerConsumption { get; set; } + public string? PowerConsumption { get; set; } } } diff --git a/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/MiningEquipmentsResponse.cs b/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/MiningEquipmentsResponse.cs index 387195a..c513956 100644 --- a/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/MiningEquipmentsResponse.cs +++ b/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/MiningEquipmentsResponse.cs @@ -1,9 +1,10 @@ using System.Collections.Generic; +using System.Collections.Immutable; namespace Trakx.CryptoCompare.ApiClient.Rest.Models.Responses { public class MiningEquipmentsResponse : BaseApiResponse { - public IReadOnlyDictionary MiningData { get; set; } + public IReadOnlyDictionary MiningData { get; set; } = ImmutableDictionary.Empty; } } diff --git a/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/PriceAverageResponse.cs b/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/PriceAverageResponse.cs index 1b16b88..d75a194 100644 --- a/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/PriceAverageResponse.cs +++ b/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/PriceAverageResponse.cs @@ -5,9 +5,9 @@ namespace Trakx.CryptoCompare.ApiClient.Rest.Models.Responses public class PriceAverageResponse { [JsonProperty("DISPLAY")] - public CoinFullAggregatedDataDisplay Display { get; set; } + public CoinFullAggregatedDataDisplay? Display { get; set; } [JsonProperty("RAW")] - public CoinFullAggregatedData Raw { get; set; } + public CoinFullAggregatedData? Raw { get; set; } } } diff --git a/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/PriceMultiFullResponse.cs b/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/PriceMultiFullResponse.cs index dbc60c7..9c9132d 100644 --- a/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/PriceMultiFullResponse.cs +++ b/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/PriceMultiFullResponse.cs @@ -5,9 +5,9 @@ namespace Trakx.CryptoCompare.ApiClient.Rest.Models.Responses public class PriceMultiFullResponse { [JsonProperty("DISPLAY")] - public PriceMultiFullDisplay Display { get; set; } + public PriceMultiFullDisplay? Display { get; set; } [JsonProperty("RAW")] - public PriceMultiFullRaw Raw { get; set; } + public PriceMultiFullRaw? Raw { get; set; } } } diff --git a/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/SEO.cs b/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/SEO.cs index eab2218..f665e57 100644 --- a/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/SEO.cs +++ b/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/SEO.cs @@ -1,19 +1,19 @@ namespace Trakx.CryptoCompare.ApiClient.Rest.Models.Responses { - public class SEO + public class Seo { - public string BaseImageUrl { get; set; } + public string? BaseImageUrl { get; set; } - public string BaseUrl { get; set; } + public string? BaseUrl { get; set; } public int OgImageHeight { get; set; } - public string OgImageUrl { get; set; } + public string? OgImageUrl { get; set; } public int OgImageWidth { get; set; } - public string PageDescription { get; set; } + public string? PageDescription { get; set; } - public string PageTitle { get; set; } + public string? PageTitle { get; set; } } } diff --git a/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/Sub.cs b/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/Sub.cs index 88c95de..d327f54 100644 --- a/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/Sub.cs +++ b/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/Sub.cs @@ -1,19 +1,19 @@ using System; -using JetBrains.Annotations; using Trakx.CryptoCompare.ApiClient.Rest.Helpers; namespace Trakx.CryptoCompare.ApiClient.Rest.Models.Responses { public readonly struct Sub : IEquatable { - public bool Equals(Sub other) => string.Equals(this.Exchange, other.Exchange) - && string.Equals(this.BaseSymbol, other.BaseSymbol) - && this.SubId == other.SubId - && string.Equals(this.QuoteSymbol, other.QuoteSymbol); + public bool Equals(Sub other) + => string.Equals(this.Exchange, other.Exchange) + && string.Equals(this.BaseSymbol, other.BaseSymbol) + && this.SubId == other.SubId + && string.Equals(this.QuoteSymbol, other.QuoteSymbol); - public override bool Equals(object obj) + public override bool Equals(object? obj) { - if (ReferenceEquals(null, obj)) + if (obj is null) { return false; } @@ -22,25 +22,18 @@ public override bool Equals(object obj) public override int GetHashCode() { - unchecked - { - var hashCode = this.Exchange.GetHashCode(); - hashCode = (hashCode * 397) ^ this.BaseSymbol.GetHashCode(); - hashCode = (hashCode * 397) ^ (int)this.SubId; - hashCode = (hashCode * 397) ^ this.QuoteSymbol.GetHashCode(); - return hashCode; - } + return HashCode.Combine(Exchange, BaseSymbol, SubId, QuoteSymbol); } - public Sub([NotNull] string exchange, [NotNull] string fromSymbol, SubId subId, [NotNull] string toSymbol) + public Sub(string? exchange, string? fromSymbol, SubId subId, string? toSymbol) { Check.NotNullOrWhiteSpace(exchange, nameof(exchange)); Check.NotNullOrWhiteSpace(fromSymbol, nameof(fromSymbol)); Check.NotNullOrWhiteSpace(toSymbol, nameof(toSymbol)); - this.Exchange = exchange; - this.BaseSymbol = fromSymbol; + this.Exchange = exchange!; + this.BaseSymbol = fromSymbol!; this.SubId = subId; - this.QuoteSymbol = toSymbol; + this.QuoteSymbol = toSymbol!; } public string Exchange { get; } @@ -55,5 +48,15 @@ public override string ToString() { return $"{this.SubId:D}~{this.Exchange}~{this.BaseSymbol}~{this.QuoteSymbol}"; } + + public static bool operator ==(Sub left, Sub right) + { + return left.Equals(right); + } + + public static bool operator !=(Sub left, Sub right) + { + return !(left == right); + } } } diff --git a/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/SubListResponse.cs b/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/SubListResponse.cs index 6eb2c4f..635b9e8 100644 --- a/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/SubListResponse.cs +++ b/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/SubListResponse.cs @@ -16,12 +16,12 @@ public SubListResponse(IDictionary dictionary) public class SubList { [JsonConverter(typeof(StringToSubConverter))] - public IReadOnlyList Current { get; set; } + public IReadOnlyList? Current { get; set; } [JsonConverter(typeof(StringToSubConverter))] - public Sub CurrentAgg { get; set; } + public Sub? CurrentAgg { get; set; } [JsonConverter(typeof(StringToSubConverter))] - public IReadOnlyList Trades { get; set; } + public IReadOnlyList? Trades { get; set; } } } diff --git a/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/TopVolume24HInfo.cs b/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/TopVolume24HInfo.cs index 9b4ae92..b73dd2a 100644 --- a/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/TopVolume24HInfo.cs +++ b/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/TopVolume24HInfo.cs @@ -4,12 +4,12 @@ namespace Trakx.CryptoCompare.ApiClient.Rest.Models.Responses { public class TopVolume24HInfo { - public CoinInfo CoinInfo { get; set; } + public CoinInfo? CoinInfo { get; set; } [JsonProperty("DISPLAY")] - public Volume24HDisplay Display { get; set; } + public Volume24HDisplay? Display { get; set; } [JsonProperty("RAW")] - public Volume24HRaw Raw { get; set; } + public Volume24HRaw? Raw { get; set; } } } diff --git a/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/TopVolume24HResponse.cs b/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/TopVolume24HResponse.cs index ef97b2c..8c7114a 100644 --- a/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/TopVolume24HResponse.cs +++ b/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/TopVolume24HResponse.cs @@ -4,6 +4,6 @@ namespace Trakx.CryptoCompare.ApiClient.Rest.Models.Responses { public class TopVolume24HResponse : BaseApiResponse { - public IReadOnlyList Data { get; set; } + public IReadOnlyList? Data { get; set; } } } diff --git a/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/TopVolumesResponse.cs b/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/TopVolumesResponse.cs index 1468cd4..cc681c2 100644 --- a/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/TopVolumesResponse.cs +++ b/src/Trakx.CryptoCompare.ApiClient/Rest/Models/Responses/TopVolumesResponse.cs @@ -1,11 +1,12 @@ using System.Collections.Generic; +using System.Collections.Immutable; namespace Trakx.CryptoCompare.ApiClient.Rest.Models.Responses { public class TopVolumesResponse : BaseApiResponse { - public IReadOnlyList Data { get; set; } + public IReadOnlyList Data { get; set; } = ImmutableList.Empty; - public string VolSymbol { get; set; } + public string? VolSymbol { get; set; } } } diff --git a/src/Trakx.CryptoCompare.ApiClient/ServiceConfiguration.cs b/src/Trakx.CryptoCompare.ApiClient/ServiceConfiguration.cs index c08033e..07ebbd4 100644 --- a/src/Trakx.CryptoCompare.ApiClient/ServiceConfiguration.cs +++ b/src/Trakx.CryptoCompare.ApiClient/ServiceConfiguration.cs @@ -1,5 +1,6 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using Trakx.Common.Configuration; using Trakx.CryptoCompare.ApiClient.Rest; namespace Trakx.CryptoCompare.ApiClient @@ -16,8 +17,7 @@ public static IServiceCollection AddCryptoCompareClient( public static IServiceCollection AddCryptoCompareClient(this IServiceCollection services, IConfiguration configuration) { - var apiConfiguration = configuration.GetSection(nameof(CryptoCompareApiConfiguration)) - .Get(); + var apiConfiguration = configuration.GetConfiguration(); return AddCryptoCompareClient(services, apiConfiguration); } } diff --git a/src/Trakx.CryptoCompare.ApiClient/Trakx.CryptoCompare.ApiClient.csproj b/src/Trakx.CryptoCompare.ApiClient/Trakx.CryptoCompare.ApiClient.csproj index 905ca71..b16d03a 100644 --- a/src/Trakx.CryptoCompare.ApiClient/Trakx.CryptoCompare.ApiClient.csproj +++ b/src/Trakx.CryptoCompare.ApiClient/Trakx.CryptoCompare.ApiClient.csproj @@ -10,8 +10,9 @@ - - + + +