From a26bc986ef15edf62723d086cda83b6a0d5bd982 Mon Sep 17 00:00:00 2001 From: Jkorf Date: Mon, 18 Nov 2024 14:38:44 +0100 Subject: [PATCH 1/2] wip --- CoinEx.Net.UnitTests/CoinExClientTests.cs | 103 ++++++++++++++++ .../CoinExRestIntegrationTests.cs | 9 +- CoinEx.Net/Clients/CoinExRestClient.cs | 23 ++-- CoinEx.Net/Clients/CoinExSocketClient.cs | 30 ++--- CoinEx.Net/CoinEx.Net.csproj | 4 +- CoinEx.Net/CoinEx.Net.xml | 85 ++++++++++--- CoinEx.Net/CoinExEnvironment.cs | 20 +++ .../ServiceCollectionExtensions.cs | 116 ++++++++++++++---- CoinEx.Net/Objects/Options/CoinExOptions.cs | 39 ++++++ .../Objects/Options/CoinExRestOptions.cs | 24 ++-- .../Objects/Options/CoinExSocketOptions.cs | 22 ++-- 11 files changed, 382 insertions(+), 93 deletions(-) create mode 100644 CoinEx.Net/Objects/Options/CoinExOptions.cs diff --git a/CoinEx.Net.UnitTests/CoinExClientTests.cs b/CoinEx.Net.UnitTests/CoinExClientTests.cs index da8af9e..ee470ba 100644 --- a/CoinEx.Net.UnitTests/CoinExClientTests.cs +++ b/CoinEx.Net.UnitTests/CoinExClientTests.cs @@ -23,6 +23,9 @@ using CryptoExchange.Net.Clients; using System.Net.Http; using CryptoExchange.Net.Converters.JsonNet; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using CoinEx.Net.Interfaces.Clients; namespace CoinEx.Net.UnitTests { @@ -160,5 +163,105 @@ public void CheckInterfaces() CryptoExchange.Net.Testing.TestHelpers.CheckForMissingRestInterfaces(); CryptoExchange.Net.Testing.TestHelpers.CheckForMissingSocketInterfaces(); } + + [Test] + [TestCase(TradeEnvironmentNames.Live, "https://api.coinex.com")] + [TestCase("", "https://api.coinex.com")] + public void TestConstructorEnvironments(string environmentName, string expected) + { + var configuration = new ConfigurationBuilder() + .AddInMemoryCollection(new Dictionary + { + { "CoinEx:Environment:Name", environmentName }, + }).Build(); + + var collection = new ServiceCollection(); + collection.AddCoinEx(configuration.GetSection("CoinEx")); + var provider = collection.BuildServiceProvider(); + + var client = provider.GetRequiredService(); + + var address = client.SpotApiV2.BaseAddress; + + Assert.That(address, Is.EqualTo(expected)); + } + + [Test] + public void TestConstructorNullEnvironment() + { + var configuration = new ConfigurationBuilder() + .AddInMemoryCollection(new Dictionary + { + { "CoinEx", null }, + }).Build(); + + var collection = new ServiceCollection(); + collection.AddCoinEx(configuration.GetSection("CoinEx")); + var provider = collection.BuildServiceProvider(); + + var client = provider.GetRequiredService(); + + var address = client.SpotApiV2.BaseAddress; + + Assert.That(address, Is.EqualTo("https://api.coinex.com")); + } + + [Test] + public void TestConstructorApiOverwriteEnvironment() + { + var configuration = new ConfigurationBuilder() + .AddInMemoryCollection(new Dictionary + { + { "CoinEx:Environment:Name", "test" }, + { "CoinEx:Rest:Environment:Name", "live" }, + }).Build(); + + var collection = new ServiceCollection(); + collection.AddCoinEx(configuration.GetSection("CoinEx")); + var provider = collection.BuildServiceProvider(); + + var client = provider.GetRequiredService(); + + var address = client.SpotApiV2.BaseAddress; + + Assert.That(address, Is.EqualTo("https://api.coinex.com")); + } + + [Test] + public void TestConstructorConfiguration() + { + var configuration = new ConfigurationBuilder() + .AddInMemoryCollection(new Dictionary + { + { "ApiCredentials:Key", "123" }, + { "ApiCredentials:Secret", "456" }, + { "ApiCredentials:Memo", "000" }, + { "Socket:ApiCredentials:Key", "456" }, + { "Socket:ApiCredentials:Secret", "789" }, + { "Socket:ApiCredentials:Memo", "xxx" }, + { "Rest:OutputOriginalData", "true" }, + { "Socket:OutputOriginalData", "false" }, + { "Rest:Proxy:Host", "host" }, + { "Rest:Proxy:Port", "80" }, + { "Socket:Proxy:Host", "host2" }, + { "Socket:Proxy:Port", "81" }, + }).Build(); + + var collection = new ServiceCollection(); + collection.AddCoinEx(configuration); + var provider = collection.BuildServiceProvider(); + + var restClient = provider.GetRequiredService(); + var socketClient = provider.GetRequiredService(); + + Assert.That(((BaseApiClient)restClient.SpotApiV2).OutputOriginalData, Is.True); + Assert.That(((BaseApiClient)socketClient.SpotApiV2).OutputOriginalData, Is.False); + Assert.That(((BaseApiClient)restClient.SpotApiV2).AuthenticationProvider.ApiKey, Is.EqualTo("123")); + Assert.That(((BaseApiClient)socketClient.SpotApiV2).AuthenticationProvider.ApiKey, Is.EqualTo("456")); + Assert.That(((BaseApiClient)restClient.SpotApiV2).ClientOptions.Proxy.Host, Is.EqualTo("host")); + Assert.That(((BaseApiClient)restClient.SpotApiV2).ClientOptions.Proxy.Port, Is.EqualTo(80)); + Assert.That(((BaseApiClient)socketClient.SpotApiV2).ClientOptions.Proxy.Host, Is.EqualTo("host2")); + Assert.That(((BaseApiClient)socketClient.SpotApiV2).ClientOptions.Proxy.Port, Is.EqualTo(81)); + } } } diff --git a/CoinEx.Net.UnitTests/CoinExRestIntegrationTests.cs b/CoinEx.Net.UnitTests/CoinExRestIntegrationTests.cs index 494f7e7..7c84f30 100644 --- a/CoinEx.Net.UnitTests/CoinExRestIntegrationTests.cs +++ b/CoinEx.Net.UnitTests/CoinExRestIntegrationTests.cs @@ -3,6 +3,7 @@ using CryptoExchange.Net.Authentication; using CryptoExchange.Net.Testing; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using NUnit.Framework; using System; using System.Collections.Generic; @@ -27,11 +28,11 @@ public override CoinExRestClient GetClient(ILoggerFactory loggerFactory) var sec = Environment.GetEnvironmentVariable("APISECRET"); Authenticated = key != null && sec != null; - return new CoinExRestClient(null, loggerFactory, opts => + return new CoinExRestClient(null, loggerFactory, Options.Create(new Objects.Options.CoinExRestOptions { - opts.OutputOriginalData = true; - opts.ApiCredentials = Authenticated ? new ApiCredentials(key, sec) : null; - }); + OutputOriginalData = true, + ApiCredentials = Authenticated ? new ApiCredentials(key, sec) : null + })); } [Test] diff --git a/CoinEx.Net/Clients/CoinExRestClient.cs b/CoinEx.Net/Clients/CoinExRestClient.cs index 85f4c99..06cf80b 100644 --- a/CoinEx.Net/Clients/CoinExRestClient.cs +++ b/CoinEx.Net/Clients/CoinExRestClient.cs @@ -7,6 +7,7 @@ using CryptoExchange.Net.Clients; using CoinEx.Net.Interfaces.Clients.FuturesApi; using CoinEx.Net.Clients.FuturesApi; +using Microsoft.Extensions.Options; namespace CoinEx.Net.Clients { @@ -27,27 +28,25 @@ public class CoinExRestClient : BaseRestClient, ICoinExRestClient /// Create a new instance of the CoinExRestClient using provided options /// /// Option configuration delegate - public CoinExRestClient(Action? optionsDelegate = null) : this(null, null, optionsDelegate) + public CoinExRestClient(Action? optionsDelegate = null) + : this(null, null, Options.Create(ApplyOptionsDelegate(optionsDelegate))) { } /// /// Create a new instance of the CoinExRestClient /// - /// Option configuration delegate + /// Option configuration /// The logger factory /// Http client for this client - public CoinExRestClient(HttpClient? httpClient, ILoggerFactory? loggerFactory, Action? optionsDelegate = null) + public CoinExRestClient(HttpClient? httpClient, ILoggerFactory? loggerFactory, IOptions options) : base(loggerFactory, "CoinEx") { - var options = CoinExRestOptions.Default.Copy(); - if (optionsDelegate != null) - optionsDelegate(options); - Initialize(options); + Initialize(options.Value); - FuturesApi = AddApiClient(new CoinExRestClientFuturesApi(_logger, httpClient, options)); - SpotApi = AddApiClient(new SpotApiV1.CoinExRestClientSpotApi(_logger, httpClient, options)); - SpotApiV2 = AddApiClient(new SpotApiV2.CoinExRestClientSpotApi(_logger, httpClient, options)); + FuturesApi = AddApiClient(new CoinExRestClientFuturesApi(_logger, httpClient, options.Value)); + SpotApi = AddApiClient(new SpotApiV1.CoinExRestClientSpotApi(_logger, httpClient, options.Value)); + SpotApiV2 = AddApiClient(new SpotApiV2.CoinExRestClientSpotApi(_logger, httpClient, options.Value)); } #endregion @@ -58,9 +57,7 @@ public CoinExRestClient(HttpClient? httpClient, ILoggerFactory? loggerFactory, A /// Option configuration delegate public static void SetDefaultOptions(Action optionsDelegate) { - var options = CoinExRestOptions.Default.Copy(); - optionsDelegate(options); - CoinExRestOptions.Default = options; + CoinExRestOptions.Default = ApplyOptionsDelegate(optionsDelegate); } /// diff --git a/CoinEx.Net/Clients/CoinExSocketClient.cs b/CoinEx.Net/Clients/CoinExSocketClient.cs index 787dca0..2c80004 100644 --- a/CoinEx.Net/Clients/CoinExSocketClient.cs +++ b/CoinEx.Net/Clients/CoinExSocketClient.cs @@ -6,6 +6,7 @@ using CryptoExchange.Net.Clients; using CoinEx.Net.Interfaces.Clients.FuturesApi; using CoinEx.Net.Clients.FuturesApi; +using Microsoft.Extensions.Options; namespace CoinEx.Net.Clients { @@ -25,19 +26,12 @@ public class CoinExSocketClient : BaseSocketClient, ICoinExSocketClient #region ctor - /// - /// Create a new instance of the CoinExSocketClient - /// - /// The logger factory - public CoinExSocketClient(ILoggerFactory? loggerFactory = null) : this((x) => { }, loggerFactory) - { - } - /// /// Create a new instance of the CoinExSocketClient /// /// Option configuration delegate - public CoinExSocketClient(Action optionsDelegate) : this(optionsDelegate, null) + public CoinExSocketClient(Action? optionsDelegate = null) + : this(Options.Create(ApplyOptionsDelegate(optionsDelegate)), null) { } @@ -45,16 +39,14 @@ public CoinExSocketClient(Action optionsDelegate) : this(op /// Create a new instance of the CoinExSocketClient /// /// The logger factory - /// Option configuration delegate - public CoinExSocketClient(Action optionsDelegate, ILoggerFactory? loggerFactory = null) : base(loggerFactory, "CoinEx") + /// Option configuration + public CoinExSocketClient(IOptions options, ILoggerFactory? loggerFactory = null) : base(loggerFactory, "CoinEx") { - var options = CoinExSocketOptions.Default.Copy(); - optionsDelegate(options); - Initialize(options); + Initialize(options.Value); - FuturesApi = AddApiClient(new CoinExSocketClientFuturesApi(_logger, options)); - SpotApi = AddApiClient(new SpotApiV1.CoinExSocketClientSpotApi(_logger, options)); - SpotApiV2 = AddApiClient(new SpotApiV2.CoinExSocketClientSpotApi(_logger, options)); + FuturesApi = AddApiClient(new CoinExSocketClientFuturesApi(_logger, options.Value)); + SpotApi = AddApiClient(new SpotApiV1.CoinExSocketClientSpotApi(_logger, options.Value)); + SpotApiV2 = AddApiClient(new SpotApiV2.CoinExSocketClientSpotApi(_logger, options.Value)); } #endregion @@ -64,9 +56,7 @@ public CoinExSocketClient(Action optionsDelegate, ILoggerFa /// Option configuration delegate public static void SetDefaultOptions(Action optionsDelegate) { - var options = CoinExSocketOptions.Default.Copy(); - optionsDelegate(options); - CoinExSocketOptions.Default = options; + CoinExSocketOptions.Default = ApplyOptionsDelegate(optionsDelegate); } /// diff --git a/CoinEx.Net/CoinEx.Net.csproj b/CoinEx.Net/CoinEx.Net.csproj index a4cb7e8..b69c359 100644 --- a/CoinEx.Net/CoinEx.Net.csproj +++ b/CoinEx.Net/CoinEx.Net.csproj @@ -48,11 +48,13 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - all runtime; build; native; contentfiles; analyzers; buildtransitive + + + \ No newline at end of file diff --git a/CoinEx.Net/CoinEx.Net.xml b/CoinEx.Net/CoinEx.Net.xml index 100ce47..f97a213 100644 --- a/CoinEx.Net/CoinEx.Net.xml +++ b/CoinEx.Net/CoinEx.Net.xml @@ -22,11 +22,11 @@ Option configuration delegate - + Create a new instance of the CoinExRestClient - Option configuration delegate + Option configuration The logger factory Http client for this client @@ -51,24 +51,18 @@ - - - Create a new instance of the CoinExSocketClient - - The logger factory - Create a new instance of the CoinExSocketClient Option configuration delegate - + Create a new instance of the CoinExSocketClient The logger factory - Option configuration delegate + Option configuration @@ -880,6 +874,16 @@ Spot Socket client address + + + ctor for DI, use for creating a custom environment + + + + + Get the CoinEx environment by name + + Live environment @@ -7499,6 +7503,36 @@ Remark + + + CoinEx options + + + + + Rest client options + + + + + Socket client options + + + + + Trade environment. Contains info about URL's to use to connect to the API. Use `CoinExEnvironment` to swap environment, for example `Environment = CoinExEnvironment.Live` + + + + + The api credentials used for signing requests. + + + + + The DI service lifetime for the ICoinExSocketClient + + Options for CoinEx SymbolOrderBook @@ -7529,6 +7563,11 @@ Default options for the CoinExRestClient + + + ctor + + Optional nonce provider for signing requests. Careful providing a custom provider; once a nonce is sent to the server, every request after that needs a higher nonce than that @@ -7559,6 +7598,11 @@ Default options for the CoinExRestClient + + + ctor + + Optional nonce provider for signing requests. Careful providing a custom provider; once a nonce is sent to the server, every request after that needs a higher nonce than that @@ -7700,15 +7744,26 @@ Extensions for DI - + + + Add services such as the ICoinExRestClient and ICoinExSocketClient. Configures the services based on the provided configuration. + + The service collection + The configuration(section) containing the options + + + - Add the ICoinExClient and ICoinExSocketClient to the sevice collection so they can be injected + Add services such as the ICoinExRestClient and ICoinExSocketClient. Services will be configured based on the provided options. The service collection - Set default options for the rest client - Set default options for the socket client - The lifetime of the ICoinExSocketClient for the service collection. Defaults to Singleton. + Set options for the CoinEx services + + + DEPRECATED; use instead + + diff --git a/CoinEx.Net/CoinExEnvironment.cs b/CoinEx.Net/CoinExEnvironment.cs index 9992fcd..6b75deb 100644 --- a/CoinEx.Net/CoinExEnvironment.cs +++ b/CoinEx.Net/CoinExEnvironment.cs @@ -26,6 +26,26 @@ internal CoinExEnvironment(string name, SocketBaseAddress = socketBaseAddress; } + /// + /// ctor for DI, use for creating a custom environment + /// +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable. + public CoinExEnvironment() : base(TradeEnvironmentNames.Live) +#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable. + { } + + /// + /// Get the CoinEx environment by name + /// + public static CoinExEnvironment? GetEnvironmentByName(string? name) + => name switch + { + TradeEnvironmentNames.Live => Live, + "" => Live, + null => Live, + _ => default + }; + /// /// Live environment /// diff --git a/CoinEx.Net/ExtensionMethods/ServiceCollectionExtensions.cs b/CoinEx.Net/ExtensionMethods/ServiceCollectionExtensions.cs index ec9b424..486107a 100644 --- a/CoinEx.Net/ExtensionMethods/ServiceCollectionExtensions.cs +++ b/CoinEx.Net/ExtensionMethods/ServiceCollectionExtensions.cs @@ -7,6 +7,9 @@ using CryptoExchange.Net; using CryptoExchange.Net.Clients; using CryptoExchange.Net.Interfaces; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using System; using System.Net; using System.Net.Http; @@ -19,45 +22,112 @@ namespace Microsoft.Extensions.DependencyInjection public static class ServiceCollectionExtensions { /// - /// Add the ICoinExClient and ICoinExSocketClient to the sevice collection so they can be injected + /// Add services such as the ICoinExRestClient and ICoinExSocketClient. Configures the services based on the provided configuration. /// /// The service collection - /// Set default options for the rest client - /// Set default options for the socket client - /// The lifetime of the ICoinExSocketClient for the service collection. Defaults to Singleton. + /// The configuration(section) containing the options /// public static IServiceCollection AddCoinEx( this IServiceCollection services, - Action? defaultRestOptionsDelegate = null, - Action? defaultSocketOptionsDelegate = null, - ServiceLifetime? socketClientLifeTime = null) + IConfiguration configuration) { - var restOptions = CoinExRestOptions.Default.Copy(); + var options = new CoinExOptions(); + // Reset environment so we know if theyre overriden + options.Rest.Environment = null!; + options.Socket.Environment = null!; + configuration.Bind(options); - if (defaultRestOptionsDelegate != null) - { - defaultRestOptionsDelegate(restOptions); - CoinExRestClient.SetDefaultOptions(defaultRestOptionsDelegate); - } + if (options.Rest == null || options.Socket == null) + throw new ArgumentException("Options null"); + + var restEnvName = options.Rest.Environment?.Name ?? options.Environment?.Name ?? CoinExEnvironment.Live.Name; + var socketEnvName = options.Socket.Environment?.Name ?? options.Environment?.Name ?? CoinExEnvironment.Live.Name; + options.Rest.Environment = CoinExEnvironment.GetEnvironmentByName(restEnvName) ?? options.Rest.Environment!; + options.Rest.ApiCredentials = options.Rest.ApiCredentials ?? options.ApiCredentials; + options.Socket.Environment = CoinExEnvironment.GetEnvironmentByName(socketEnvName) ?? options.Socket.Environment!; + options.Socket.ApiCredentials = options.Socket.ApiCredentials ?? options.ApiCredentials; - if (defaultSocketOptionsDelegate != null) - CoinExSocketClient.SetDefaultOptions(defaultSocketOptionsDelegate); - services.AddHttpClient(options => + services.AddSingleton(x => Options.Options.Create(options.Rest)); + services.AddSingleton(x => Options.Options.Create(options.Socket)); + + return AddCoinExCore(services, options.SocketClientLifeTime); + } + + /// + /// Add services such as the ICoinExRestClient and ICoinExSocketClient. Services will be configured based on the provided options. + /// + /// The service collection + /// Set options for the CoinEx services + /// + public static IServiceCollection AddCoinEx( + this IServiceCollection services, + Action? optionsDelegate = null) + { + var options = new CoinExOptions(); + // Reset environment so we know if theyre overriden + options.Rest.Environment = null!; + options.Socket.Environment = null!; + optionsDelegate?.Invoke(options); + if (options.Rest == null || options.Socket == null) + throw new ArgumentException("Options null"); + + options.Rest.Environment = options.Rest.Environment ?? options.Environment ?? CoinExEnvironment.Live; + options.Rest.ApiCredentials = options.Rest.ApiCredentials ?? options.ApiCredentials; + options.Socket.Environment = options.Socket.Environment ?? options.Environment ?? CoinExEnvironment.Live; + options.Socket.ApiCredentials = options.Socket.ApiCredentials ?? options.ApiCredentials; + + services.AddSingleton(x => Options.Options.Create(options.Rest)); + services.AddSingleton(x => Options.Options.Create(options.Socket)); + + return AddCoinExCore(services, options.SocketClientLifeTime); + } + + /// + /// DEPRECATED; use instead + /// + public static IServiceCollection AddCoinEx( + this IServiceCollection services, + Action restDelegate, + Action? socketDelegate = null, + ServiceLifetime? socketClientLifeTime = null) + { + services.Configure((x) => { restDelegate?.Invoke(x); }); + services.Configure((x) => { socketDelegate?.Invoke(x); }); + + return AddCoinExCore(services, socketClientLifeTime); + } + + private static IServiceCollection AddCoinExCore( + this IServiceCollection services, + ServiceLifetime? socketClientLifeTime = null) + { + services.AddHttpClient((client, serviceProvider) => { - options.Timeout = restOptions.RequestTimeout; - }).ConfigurePrimaryHttpMessageHandler(() => { + var options = serviceProvider.GetRequiredService>().Value; + client.Timeout = options.RequestTimeout; + return new CoinExRestClient(client, serviceProvider.GetRequiredService(), serviceProvider.GetRequiredService>()); + }).ConfigurePrimaryHttpMessageHandler((serviceProvider) => { var handler = new HttpClientHandler(); - if (restOptions.Proxy != null) + try + { + handler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; + } + catch (PlatformNotSupportedException) + { } + + var options = serviceProvider.GetRequiredService>().Value; + if (options.Proxy != null) { handler.Proxy = new WebProxy { - Address = new Uri($"{restOptions.Proxy.Host}:{restOptions.Proxy.Port}"), - Credentials = restOptions.Proxy.Password == null ? null : new NetworkCredential(restOptions.Proxy.Login, restOptions.Proxy.Password) + Address = new Uri($"{options.Proxy.Host}:{options.Proxy.Port}"), + Credentials = options.Proxy.Password == null ? null : new NetworkCredential(options.Proxy.Login, options.Proxy.Password) }; } return handler; }); + services.Add(new ServiceDescriptor(typeof(ICoinExSocketClient), x => { return new CoinExSocketClient(x.GetRequiredService>(), x.GetRequiredService()); }, socketClientLifeTime ?? ServiceLifetime.Singleton)); services.AddTransient(); services.AddTransient(); @@ -70,10 +140,6 @@ public static IServiceCollection AddCoinEx( services.RegisterSharedRestInterfaces(x => x.GetRequiredService().FuturesApi.SharedClient); services.RegisterSharedSocketInterfaces(x => x.GetRequiredService().FuturesApi.SharedClient); - if (socketClientLifeTime == null) - services.AddSingleton(); - else - services.Add(new ServiceDescriptor(typeof(ICoinExSocketClient), typeof(CoinExSocketClient), socketClientLifeTime.Value)); return services; } } diff --git a/CoinEx.Net/Objects/Options/CoinExOptions.cs b/CoinEx.Net/Objects/Options/CoinExOptions.cs new file mode 100644 index 0000000..d4dd4a4 --- /dev/null +++ b/CoinEx.Net/Objects/Options/CoinExOptions.cs @@ -0,0 +1,39 @@ +using CryptoExchange.Net.Authentication; +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using System.Text; + +namespace CoinEx.Net.Objects.Options +{ + /// + /// CoinEx options + /// + public class CoinExOptions + { + /// + /// Rest client options + /// + public CoinExRestOptions Rest { get; set; } = new CoinExRestOptions(); + + /// + /// Socket client options + /// + public CoinExSocketOptions Socket { get; set; } = new CoinExSocketOptions(); + + /// + /// Trade environment. Contains info about URL's to use to connect to the API. Use `CoinExEnvironment` to swap environment, for example `Environment = CoinExEnvironment.Live` + /// + public CoinExEnvironment? Environment { get; set; } + + /// + /// The api credentials used for signing requests. + /// + public ApiCredentials? ApiCredentials { get; set; } + + /// + /// The DI service lifetime for the ICoinExSocketClient + /// + public ServiceLifetime? SocketClientLifeTime { get; set; } + } +} diff --git a/CoinEx.Net/Objects/Options/CoinExRestOptions.cs b/CoinEx.Net/Objects/Options/CoinExRestOptions.cs index c74a0f7..e2f6c10 100644 --- a/CoinEx.Net/Objects/Options/CoinExRestOptions.cs +++ b/CoinEx.Net/Objects/Options/CoinExRestOptions.cs @@ -11,11 +11,19 @@ public class CoinExRestOptions : RestExchangeOptions /// /// Default options for the CoinExRestClient /// - public static CoinExRestOptions Default { get; set; } = new CoinExRestOptions + internal static CoinExRestOptions Default { get; set; } = new CoinExRestOptions { Environment = CoinExEnvironment.Live }; + /// + /// ctor + /// + public CoinExRestOptions() + { + Default?.Set(this); + } + /// /// Optional nonce provider for signing requests. Careful providing a custom provider; once a nonce is sent to the server, every request after that needs a higher nonce than that /// @@ -36,14 +44,14 @@ public class CoinExRestOptions : RestExchangeOptions /// public string? BrokerId { get; set; } - internal CoinExRestOptions Copy() + internal CoinExRestOptions Set(CoinExRestOptions targetOptions) { - var options = Copy(); - options.BrokerId = BrokerId; - options.NonceProvider = NonceProvider; - options.SpotOptions = SpotOptions.Copy(); - options.FuturesOptions = SpotOptions.Copy(); - return options; + targetOptions = base.Set(targetOptions); + targetOptions.BrokerId = BrokerId; + targetOptions.NonceProvider = NonceProvider; + targetOptions.SpotOptions = SpotOptions.Set(targetOptions.SpotOptions); + targetOptions.FuturesOptions = FuturesOptions.Set(targetOptions.FuturesOptions); + return targetOptions; } } } diff --git a/CoinEx.Net/Objects/Options/CoinExSocketOptions.cs b/CoinEx.Net/Objects/Options/CoinExSocketOptions.cs index 7046132..64c881c 100644 --- a/CoinEx.Net/Objects/Options/CoinExSocketOptions.cs +++ b/CoinEx.Net/Objects/Options/CoinExSocketOptions.cs @@ -11,12 +11,20 @@ public class CoinExSocketOptions : SocketExchangeOptions /// /// Default options for the CoinExRestClient /// - public static CoinExSocketOptions Default { get; set; } = new CoinExSocketOptions + internal static CoinExSocketOptions Default { get; set; } = new CoinExSocketOptions { Environment = CoinExEnvironment.Live, SocketSubscriptionsCombineTarget = 10 }; + /// + /// ctor + /// + public CoinExSocketOptions() + { + Default?.Set(this); + } + /// /// Optional nonce provider for signing requests. Careful providing a custom provider; once a nonce is sent to the server, every request after that needs a higher nonce than that /// @@ -32,13 +40,13 @@ public class CoinExSocketOptions : SocketExchangeOptions /// public SocketApiOptions FuturesOptions { get; private set; } = new SocketApiOptions(); - internal CoinExSocketOptions Copy() + internal CoinExSocketOptions Set(CoinExSocketOptions targetOptions) { - var options = Copy(); - options.NonceProvider = NonceProvider; - options.SpotOptions = SpotOptions.Copy(); - options.FuturesOptions = SpotOptions.Copy(); - return options; + targetOptions = base.Set(targetOptions); + targetOptions.NonceProvider = NonceProvider; + targetOptions.SpotOptions = SpotOptions.Set(targetOptions.SpotOptions); + targetOptions.FuturesOptions = FuturesOptions.Set(targetOptions.FuturesOptions); + return targetOptions; } } } From 6f50a101bb3af31271a682bee1885ad74cf9487d Mon Sep 17 00:00:00 2001 From: Jkorf Date: Tue, 19 Nov 2024 12:59:26 +0100 Subject: [PATCH 2/2] updated CryptoExchange ref --- CoinEx.Net/CoinEx.Net.csproj | 6 ++---- CoinEx.Net/CoinEx.Net.xml | 10 ++++++++++ CoinEx.Net/CoinExExchange.cs | 10 ++++++++++ docs/index.html | 10 ++++++++-- 4 files changed, 30 insertions(+), 6 deletions(-) diff --git a/CoinEx.Net/CoinEx.Net.csproj b/CoinEx.Net/CoinEx.Net.csproj index b69c359..0713f82 100644 --- a/CoinEx.Net/CoinEx.Net.csproj +++ b/CoinEx.Net/CoinEx.Net.csproj @@ -1,4 +1,4 @@ - + netstandard2.0;netstandard2.1 10.0 @@ -48,13 +48,11 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - \ No newline at end of file diff --git a/CoinEx.Net/CoinEx.Net.xml b/CoinEx.Net/CoinEx.Net.xml index f97a213..5c5315b 100644 --- a/CoinEx.Net/CoinEx.Net.xml +++ b/CoinEx.Net/CoinEx.Net.xml @@ -908,6 +908,16 @@ Exchange name + + + Exchange name + + + + + Url to exchange image + + Url to the main website diff --git a/CoinEx.Net/CoinExExchange.cs b/CoinEx.Net/CoinExExchange.cs index be6936e..640ef51 100644 --- a/CoinEx.Net/CoinExExchange.cs +++ b/CoinEx.Net/CoinExExchange.cs @@ -13,6 +13,16 @@ public static class CoinExExchange /// public static string ExchangeName => "CoinEx"; + /// + /// Exchange name + /// + public static string DisplayName => "CoinEx"; + + /// + /// Url to exchange image + /// + public static string ImageUrl { get; } = "https://raw.githubusercontent.com/JKorf/CoinEx.Net/master/CoinEx.Net/Icon/icon.png"; + /// /// Url to the main website /// diff --git a/docs/index.html b/docs/index.html index 4d46b11..8dac734 100644 --- a/docs/index.html +++ b/docs/index.html @@ -190,8 +190,14 @@

API Access

CoinEx.Net can be configured using Dotnet dependency injection, after which the clients can be injected into your services. It also correctly configures logging and HttpClient usage.

-
builder.Services.AddCoinEx(options => {
-  // Options can be configured here, for example:
+		  
// Configure options from config file
+// see https://github.com/JKorf/CryptoExchange.Net/tree/master/Examples/example-config.json for an example
+builder.Services.AddCoinEx(builder.Configuration.GetSection("CoinEx"));
+		  
+// OR
+		  
+ builder.Services.AddCoinEx(options => {
+  // Configure options in code
   options.ApiCredentials = new ApiCredentials("APIKEY", "APISECRET");
 });