From d0c8b104f435159dfe2fb8f3e289f3a4b228669e Mon Sep 17 00:00:00 2001 From: Jan Korf Date: Tue, 19 Nov 2024 13:26:19 +0100 Subject: [PATCH] Client Configuration (#123) Updated CryptoExchange.Net to version 8.3.0 Added support for loading client settings from IConfiguration Added DI registration method for configuring Rest and Socket options at the same time Added DisplayName and ImageUrl properties to HTXExchange class Updated client constructors to accept IOptions from DI Removed redundant HTXSocketClient constructor --- HTX.Net.UnitTests/HTXRestClientTests.cs | 102 +++++++++++++++ HTX.Net.UnitTests/HTXRestIntegrationTests.cs | 9 +- HTX.Net/Clients/HTXRestClient.cs | 21 ++-- HTX.Net/Clients/HTXSocketClient.cs | 27 ++-- .../ServiceCollectionExtensions.cs | 117 ++++++++++++++---- HTX.Net/HTX.Net.csproj | 4 +- HTX.Net/HTX.Net.xml | 95 +++++++++++--- HTX.Net/HTXEnvironment.cs | 20 +++ HTX.Net/HTXExchange.cs | 10 ++ HTX.Net/Objects/Options/HTXOptions.cs | 38 ++++++ HTX.Net/Objects/Options/HTXRestOptions.cs | 24 ++-- HTX.Net/Objects/Options/HTXSocketOptions.cs | 22 ++-- docs/index.html | 10 +- 13 files changed, 405 insertions(+), 94 deletions(-) create mode 100644 HTX.Net/Objects/Options/HTXOptions.cs diff --git a/HTX.Net.UnitTests/HTXRestClientTests.cs b/HTX.Net.UnitTests/HTXRestClientTests.cs index e603b857..ba2f4a10 100644 --- a/HTX.Net.UnitTests/HTXRestClientTests.cs +++ b/HTX.Net.UnitTests/HTXRestClientTests.cs @@ -9,6 +9,10 @@ using System.Net.Http; using System.Collections.Generic; using System.Text.Json; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using HTX.Net.Interfaces.Clients; +using CryptoExchange.Net.Objects; namespace HTX.Net.UnitTests { @@ -83,5 +87,103 @@ public void CheckInterfaces() CryptoExchange.Net.Testing.TestHelpers.CheckForMissingRestInterfaces(); CryptoExchange.Net.Testing.TestHelpers.CheckForMissingSocketInterfaces(); } + + [Test] + [TestCase(TradeEnvironmentNames.Live, "https://api.huobi.pro")] + [TestCase("", "https://api.huobi.pro")] + public void TestConstructorEnvironments(string environmentName, string expected) + { + var configuration = new ConfigurationBuilder() + .AddInMemoryCollection(new Dictionary + { + { "HTX:Environment:Name", environmentName }, + }).Build(); + + var collection = new ServiceCollection(); + collection.AddHTX(configuration.GetSection("HTX")); + var provider = collection.BuildServiceProvider(); + + var client = provider.GetRequiredService(); + + var address = client.SpotApi.BaseAddress; + + Assert.That(address, Is.EqualTo(expected)); + } + + [Test] + public void TestConstructorNullEnvironment() + { + var configuration = new ConfigurationBuilder() + .AddInMemoryCollection(new Dictionary + { + { "HTX", null }, + }).Build(); + + var collection = new ServiceCollection(); + collection.AddHTX(configuration.GetSection("HTX")); + var provider = collection.BuildServiceProvider(); + + var client = provider.GetRequiredService(); + + var address = client.SpotApi.BaseAddress; + + Assert.That(address, Is.EqualTo("https://api.huobi.pro")); + } + + [Test] + public void TestConstructorApiOverwriteEnvironment() + { + var configuration = new ConfigurationBuilder() + .AddInMemoryCollection(new Dictionary + { + { "HTX:Environment:Name", "test" }, + { "HTX:Rest:Environment:Name", "live" }, + }).Build(); + + var collection = new ServiceCollection(); + collection.AddHTX(configuration.GetSection("HTX")); + var provider = collection.BuildServiceProvider(); + + var client = provider.GetRequiredService(); + + var address = client.SpotApi.BaseAddress; + + Assert.That(address, Is.EqualTo("https://api.huobi.pro")); + } + + [Test] + public void TestConstructorConfiguration() + { + var configuration = new ConfigurationBuilder() + .AddInMemoryCollection(new Dictionary + { + { "ApiCredentials:Key", "123" }, + { "ApiCredentials:Secret", "456" }, + { "Socket:ApiCredentials:Key", "456" }, + { "Socket:ApiCredentials:Secret", "789" }, + { "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.AddHTX(configuration); + var provider = collection.BuildServiceProvider(); + + var restClient = provider.GetRequiredService(); + var socketClient = provider.GetRequiredService(); + + Assert.That(((BaseApiClient)restClient.SpotApi).OutputOriginalData, Is.True); + Assert.That(((BaseApiClient)socketClient.SpotApi).OutputOriginalData, Is.False); + Assert.That(((BaseApiClient)restClient.SpotApi).AuthenticationProvider.ApiKey, Is.EqualTo("123")); + Assert.That(((BaseApiClient)socketClient.SpotApi).AuthenticationProvider.ApiKey, Is.EqualTo("456")); + Assert.That(((BaseApiClient)restClient.SpotApi).ClientOptions.Proxy.Host, Is.EqualTo("host")); + Assert.That(((BaseApiClient)restClient.SpotApi).ClientOptions.Proxy.Port, Is.EqualTo(80)); + Assert.That(((BaseApiClient)socketClient.SpotApi).ClientOptions.Proxy.Host, Is.EqualTo("host2")); + Assert.That(((BaseApiClient)socketClient.SpotApi).ClientOptions.Proxy.Port, Is.EqualTo(81)); + } } } diff --git a/HTX.Net.UnitTests/HTXRestIntegrationTests.cs b/HTX.Net.UnitTests/HTXRestIntegrationTests.cs index 4764942d..28cf3846 100644 --- a/HTX.Net.UnitTests/HTXRestIntegrationTests.cs +++ b/HTX.Net.UnitTests/HTXRestIntegrationTests.cs @@ -10,6 +10,7 @@ using System.Text; using System.Threading.Tasks; using HTX.Net.Enums; +using Microsoft.Extensions.Options; namespace HTX.Net.UnitTests { @@ -28,11 +29,11 @@ public override HTXRestClient GetClient(ILoggerFactory loggerFactory) var sec = Environment.GetEnvironmentVariable("APISECRET"); Authenticated = key != null && sec != null; - return new HTXRestClient(null, loggerFactory, opts => + return new HTXRestClient(null, loggerFactory, Options.Create(new Objects.Options.HTXRestOptions { - opts.OutputOriginalData = true; - opts.ApiCredentials = Authenticated ? new ApiCredentials(key, sec) : null; - }); + OutputOriginalData = true, + ApiCredentials = Authenticated ? new ApiCredentials(key, sec) : null + })); } [Test] diff --git a/HTX.Net/Clients/HTXRestClient.cs b/HTX.Net/Clients/HTXRestClient.cs index 69b99022..4856e733 100644 --- a/HTX.Net/Clients/HTXRestClient.cs +++ b/HTX.Net/Clients/HTXRestClient.cs @@ -5,6 +5,7 @@ using CryptoExchange.Net.Clients; using HTX.Net.Interfaces.Clients.UsdtFuturesApi; using HTX.Net.Clients.UsdtFutures; +using Microsoft.Extensions.Options; namespace HTX.Net.Clients { @@ -26,26 +27,24 @@ public class HTXRestClient : BaseRestClient, IHTXRestClient /// Create a new instance of the HTXRestClient using provided options /// /// Option configuration delegate - public HTXRestClient(Action? optionsDelegate = null) : this(null, null, optionsDelegate) + public HTXRestClient(Action? optionsDelegate = null) + : this(null, null, Options.Create(ApplyOptionsDelegate(optionsDelegate))) { } /// /// Create a new instance of the HTXRestClient /// - /// Option configuration delegate + /// Option configuration delegate /// The logger factory /// Http client for this client - public HTXRestClient(HttpClient? httpClient, ILoggerFactory? loggerFactory, Action? optionsDelegate = null) + public HTXRestClient(HttpClient? httpClient, ILoggerFactory? loggerFactory, IOptions options) : base(loggerFactory, "HTX") { - var options = HTXRestOptions.Default.Copy(); - if (optionsDelegate != null) - optionsDelegate(options); - Initialize(options); + Initialize(options.Value); - SpotApi = AddApiClient(new HTXRestClientSpotApi(_logger, httpClient, options)); - UsdtFuturesApi = AddApiClient(new HTXRestClientUsdtFuturesApi(_logger, httpClient, options)); + SpotApi = AddApiClient(new HTXRestClientSpotApi(_logger, httpClient, options.Value)); + UsdtFuturesApi = AddApiClient(new HTXRestClientUsdtFuturesApi(_logger, httpClient, options.Value)); } #endregion @@ -56,9 +55,7 @@ public HTXRestClient(HttpClient? httpClient, ILoggerFactory? loggerFactory, Acti /// Option configuration delegate public static void SetDefaultOptions(Action optionsDelegate) { - var options = HTXRestOptions.Default.Copy(); - optionsDelegate(options); - HTXRestOptions.Default = options; + HTXRestOptions.Default = ApplyOptionsDelegate(optionsDelegate); } /// diff --git a/HTX.Net/Clients/HTXSocketClient.cs b/HTX.Net/Clients/HTXSocketClient.cs index fff8b4b0..e90afa0b 100644 --- a/HTX.Net/Clients/HTXSocketClient.cs +++ b/HTX.Net/Clients/HTXSocketClient.cs @@ -5,6 +5,7 @@ using HTX.Net.Interfaces.Clients.SpotApi; using HTX.Net.Interfaces.Clients.UsdtFuturesApi; using HTX.Net.Objects.Options; +using Microsoft.Extensions.Options; namespace HTX.Net.Clients { @@ -19,19 +20,13 @@ public class HTXSocketClient : BaseSocketClient, IHTXSocketClient #endregion #region ctor - /// - /// Create a new instance of the HTXSocketClient - /// - /// The logger factory - public HTXSocketClient(ILoggerFactory? loggerFactory = null) : this((x) => { }, loggerFactory) - { - } /// /// Create a new instance of the HTXSocketClient /// /// Option configuration delegate - public HTXSocketClient(Action optionsDelegate) : this(optionsDelegate, null) + public HTXSocketClient(Action? optionsDelegate = null) + : this(Options.Create(ApplyOptionsDelegate(optionsDelegate)), null) { } @@ -39,15 +34,13 @@ public HTXSocketClient(Action optionsDelegate) : this(optionsD /// Create a new instance of the HTXSocketClient /// /// The logger factory - /// Option configuration delegate - public HTXSocketClient(Action optionsDelegate, ILoggerFactory? loggerFactory = null) : base(loggerFactory, "HTX") + /// Option configuration + public HTXSocketClient(IOptions options, ILoggerFactory? loggerFactory = null) : base(loggerFactory, "HTX") { - var options = HTXSocketOptions.Default.Copy(); - optionsDelegate(options); - Initialize(options); + Initialize(options.Value); - SpotApi = AddApiClient(new HTXSocketClientSpotApi(_logger, options)); - UsdtFuturesApi = AddApiClient(new HTXSocketClientUsdtFuturesApi(_logger, options)); + SpotApi = AddApiClient(new HTXSocketClientSpotApi(_logger, options.Value)); + UsdtFuturesApi = AddApiClient(new HTXSocketClientUsdtFuturesApi(_logger, options.Value)); } #endregion @@ -58,9 +51,7 @@ public HTXSocketClient(Action optionsDelegate, ILoggerFactory? /// Option configuration delegate public static void SetDefaultOptions(Action optionsDelegate) { - var options = HTXSocketOptions.Default.Copy(); - optionsDelegate(options); - HTXSocketOptions.Default = options; + HTXSocketOptions.Default = ApplyOptionsDelegate(optionsDelegate); } /// diff --git a/HTX.Net/ExtensionMethods/ServiceCollectionExtensions.cs b/HTX.Net/ExtensionMethods/ServiceCollectionExtensions.cs index 2f19121e..40e9c5cb 100644 --- a/HTX.Net/ExtensionMethods/ServiceCollectionExtensions.cs +++ b/HTX.Net/ExtensionMethods/ServiceCollectionExtensions.cs @@ -5,6 +5,8 @@ using HTX.Net.Interfaces.Clients; using HTX.Net.Objects.Options; using HTX.Net.SymbolOrderBooks; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Options; using System.Net; namespace Microsoft.Extensions.DependencyInjection @@ -14,47 +16,114 @@ namespace Microsoft.Extensions.DependencyInjection /// public static class ServiceCollectionExtensions { + /// - /// Add the IRestHTXClient and IHTXSocketClient to the sevice collection so they can be injected + /// Add services such as the IHTXRestClient and IHTXSocketClient. 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 IHTXSocketClient for the service collection. Defaults to Singleton. + /// The configuration(section) containing the options /// public static IServiceCollection AddHTX( this IServiceCollection services, - Action? defaultRestOptionsDelegate = null, - Action? defaultSocketOptionsDelegate = null, - ServiceLifetime? socketClientLifeTime = null) + IConfiguration configuration) { - var restOptions = HTXRestOptions.Default.Copy(); + var options = new HTXOptions(); + // Reset environment so we know if theyre overriden + options.Rest.Environment = null!; + options.Socket.Environment = null!; + configuration.Bind(options); - if (defaultRestOptionsDelegate != null) - { - defaultRestOptionsDelegate(restOptions); - HTXRestClient.SetDefaultOptions(defaultRestOptionsDelegate); - } + if (options.Rest == null || options.Socket == null) + throw new ArgumentException("Options null"); - if (defaultSocketOptionsDelegate != null) - HTXSocketClient.SetDefaultOptions(defaultSocketOptionsDelegate); + var restEnvName = options.Rest.Environment?.Name ?? options.Environment?.Name ?? HTXEnvironment.Live.Name; + var socketEnvName = options.Socket.Environment?.Name ?? options.Environment?.Name ?? HTXEnvironment.Live.Name; + options.Rest.Environment = HTXEnvironment.GetEnvironmentByName(restEnvName) ?? options.Rest.Environment!; + options.Rest.ApiCredentials = options.Rest.ApiCredentials ?? options.ApiCredentials; + options.Socket.Environment = HTXEnvironment.GetEnvironmentByName(socketEnvName) ?? options.Socket.Environment!; + options.Socket.ApiCredentials = options.Socket.ApiCredentials ?? options.ApiCredentials; - services.AddHttpClient(options => - { - options.Timeout = restOptions.RequestTimeout; - }).ConfigurePrimaryHttpMessageHandler(() => + + services.AddSingleton(x => Options.Options.Create(options.Rest)); + services.AddSingleton(x => Options.Options.Create(options.Socket)); + + return AddHTXCore(services, options.SocketClientLifeTime); + } + + /// + /// Add services such as the IHTXRestClient and IHTXSocketClient. Services will be configured based on the provided options. + /// + /// The service collection + /// Set options for the HTX services + /// + public static IServiceCollection AddHTX( + this IServiceCollection services, + Action? optionsDelegate = null) + { + var options = new HTXOptions(); + // 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 ?? HTXEnvironment.Live; + options.Rest.ApiCredentials = options.Rest.ApiCredentials ?? options.ApiCredentials; + options.Socket.Environment = options.Socket.Environment ?? options.Environment ?? HTXEnvironment.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 AddHTXCore(services, options.SocketClientLifeTime); + } + + /// + /// DEPRECATED; use instead + /// + public static IServiceCollection AddHTX( + this IServiceCollection services, + Action restDelegate, + Action? socketDelegate = null, + ServiceLifetime? socketClientLifeTime = null) + { + services.Configure((x) => { restDelegate?.Invoke(x); }); + services.Configure((x) => { socketDelegate?.Invoke(x); }); + + return AddHTXCore(services, socketClientLifeTime); + } + + private static IServiceCollection AddHTXCore( + this IServiceCollection services, + ServiceLifetime? socketClientLifeTime = null) + { + services.AddHttpClient((client, serviceProvider) => { + var options = serviceProvider.GetRequiredService>().Value; + client.Timeout = options.RequestTimeout; + return new HTXRestClient(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(IHTXSocketClient), x => { return new HTXSocketClient(x.GetRequiredService>(), x.GetRequiredService()); }, socketClientLifeTime ?? ServiceLifetime.Singleton)); services.AddTransient(); services.AddTransient(); @@ -67,10 +136,6 @@ public static IServiceCollection AddHTX( services.RegisterSharedSocketInterfaces(x => x.GetRequiredService().UsdtFuturesApi.SharedClient); services.AddTransient(x => x.GetRequiredService().SpotApi.CommonSpotClient); - if (socketClientLifeTime == null) - services.AddSingleton(); - else - services.Add(new ServiceDescriptor(typeof(IHTXSocketClient), typeof(HTXSocketClient), socketClientLifeTime.Value)); return services; } } diff --git a/HTX.Net/HTX.Net.csproj b/HTX.Net/HTX.Net.csproj index eb5c87b5..d13d9425 100644 --- a/HTX.Net/HTX.Net.csproj +++ b/HTX.Net/HTX.Net.csproj @@ -1,4 +1,4 @@ - + netstandard2.0;netstandard2.1 enable @@ -48,7 +48,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/HTX.Net/HTX.Net.xml b/HTX.Net/HTX.Net.xml index b8677483..24fc1a56 100644 --- a/HTX.Net/HTX.Net.xml +++ b/HTX.Net/HTX.Net.xml @@ -19,11 +19,11 @@ Option configuration delegate - + Create a new instance of the HTXRestClient - Option configuration delegate + Option configuration delegate The logger factory Http client for this client @@ -45,24 +45,18 @@ - - - Create a new instance of the HTXSocketClient - - The logger factory - Create a new instance of the HTXSocketClient Option configuration delegate - + Create a new instance of the HTXSocketClient The logger factory - Option configuration delegate + Option configuration @@ -3382,6 +3376,16 @@ Socket base address for the USDT margin swap API + + + ctor for DI, use for creating a custom environment + + + + + Get the HTX environment by name + + Live environment @@ -3408,6 +3412,16 @@ Exchange name + + + Exchange name + + + + + Url to exchange image + + Url to the main website @@ -17368,6 +17382,36 @@ Err msg + + + HTX options + + + + + Rest client options + + + + + Socket client options + + + + + Trade environment. Contains info about URL's to use to connect to the API. Use `HTXEnvironment` to swap environment, for example `Environment = HTXEnvironment.Live` + + + + + The api credentials used for signing requests. + + + + + The DI service lifetime for the IHTXSocketClient + + Options for the HTX SymbolOrderBook @@ -17403,6 +17447,11 @@ Default options for the HTXRestClient + + + ctor + + Whether public requests should be signed if ApiCredentials are provided. Needed for accurate rate limiting. @@ -17433,6 +17482,11 @@ Default options for the HTXSocketClient + + + ctor + + Broker id @@ -17576,15 +17630,26 @@ Extensions for DI - + + + Add services such as the IHTXRestClient and IHTXSocketClient. Configures the services based on the provided configuration. + + The service collection + The configuration(section) containing the options + + + - Add the IRestHTXClient and IHTXSocketClient to the sevice collection so they can be injected + Add services such as the IHTXRestClient and IHTXSocketClient. 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 IHTXSocketClient for the service collection. Defaults to Singleton. + Set options for the HTX services + + + DEPRECATED; use instead + + diff --git a/HTX.Net/HTXEnvironment.cs b/HTX.Net/HTXEnvironment.cs index 405bcc03..6b886e47 100644 --- a/HTX.Net/HTXEnvironment.cs +++ b/HTX.Net/HTXEnvironment.cs @@ -39,6 +39,26 @@ internal HTXEnvironment(string name, UsdtMarginSwapSocketBaseAddress = usdtMarginSwapSocketBaseAddress; } + /// + /// 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 HTXEnvironment() : 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 HTX environment by name + /// + public static HTXEnvironment? GetEnvironmentByName(string? name) + => name switch + { + TradeEnvironmentNames.Live => Live, + "" => Live, + null => Live, + _ => default + }; + /// /// Live environment /// diff --git a/HTX.Net/HTXExchange.cs b/HTX.Net/HTXExchange.cs index ab2f782e..a0728f82 100644 --- a/HTX.Net/HTXExchange.cs +++ b/HTX.Net/HTXExchange.cs @@ -16,6 +16,16 @@ public static class HTXExchange /// public static string ExchangeName => "HTX"; + /// + /// Exchange name + /// + public static string DisplayName => "HTX"; + + /// + /// Url to exchange image + /// + public static string ImageUrl { get; } = "https://raw.githubusercontent.com/JKorf/HTX.Net/master/HTX.Net/Icon/icon.png"; + /// /// Url to the main website /// diff --git a/HTX.Net/Objects/Options/HTXOptions.cs b/HTX.Net/Objects/Options/HTXOptions.cs new file mode 100644 index 00000000..f0d56096 --- /dev/null +++ b/HTX.Net/Objects/Options/HTXOptions.cs @@ -0,0 +1,38 @@ +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using System.Text; + +namespace HTX.Net.Objects.Options +{ + /// + /// HTX options + /// + public class HTXOptions + { + /// + /// Rest client options + /// + public HTXRestOptions Rest { get; set; } = new HTXRestOptions(); + + /// + /// Socket client options + /// + public HTXSocketOptions Socket { get; set; } = new HTXSocketOptions(); + + /// + /// Trade environment. Contains info about URL's to use to connect to the API. Use `HTXEnvironment` to swap environment, for example `Environment = HTXEnvironment.Live` + /// + public HTXEnvironment? Environment { get; set; } + + /// + /// The api credentials used for signing requests. + /// + public ApiCredentials? ApiCredentials { get; set; } + + /// + /// The DI service lifetime for the IHTXSocketClient + /// + public ServiceLifetime? SocketClientLifeTime { get; set; } + } +} diff --git a/HTX.Net/Objects/Options/HTXRestOptions.cs b/HTX.Net/Objects/Options/HTXRestOptions.cs index 9804e74d..a677e7d8 100644 --- a/HTX.Net/Objects/Options/HTXRestOptions.cs +++ b/HTX.Net/Objects/Options/HTXRestOptions.cs @@ -10,11 +10,19 @@ public class HTXRestOptions : RestExchangeOptions /// /// Default options for the HTXRestClient /// - public static HTXRestOptions Default { get; set; } = new HTXRestOptions() + internal static HTXRestOptions Default { get; set; } = new HTXRestOptions() { Environment = HTXEnvironment.Live }; + /// + /// ctor + /// + public HTXRestOptions() + { + Default?.Set(this); + } + /// /// Whether public requests should be signed if ApiCredentials are provided. Needed for accurate rate limiting. /// @@ -35,14 +43,14 @@ public class HTXRestOptions : RestExchangeOptions /// public RestApiOptions UsdtMarginSwapOptions { get; private set; } = new RestApiOptions(); - internal HTXRestOptions Copy() + internal HTXRestOptions Set(HTXRestOptions targetOptions) { - var options = Copy(); - options.SpotOptions = SpotOptions.Copy(); - options.UsdtMarginSwapOptions = UsdtMarginSwapOptions.Copy(); - options.SignPublicRequests = SignPublicRequests; - options.BrokerId = BrokerId; - return options; + targetOptions = base.Set(targetOptions); + targetOptions.SignPublicRequests = SignPublicRequests; + targetOptions.BrokerId = BrokerId; + targetOptions.SpotOptions = SpotOptions.Set(targetOptions.SpotOptions); + targetOptions.UsdtMarginSwapOptions = UsdtMarginSwapOptions.Set(targetOptions.UsdtMarginSwapOptions); + return targetOptions; } } } diff --git a/HTX.Net/Objects/Options/HTXSocketOptions.cs b/HTX.Net/Objects/Options/HTXSocketOptions.cs index 2c9d51dd..be8deacc 100644 --- a/HTX.Net/Objects/Options/HTXSocketOptions.cs +++ b/HTX.Net/Objects/Options/HTXSocketOptions.cs @@ -10,12 +10,20 @@ public class HTXSocketOptions : SocketExchangeOptions /// /// Default options for the HTXSocketClient /// - public static HTXSocketOptions Default { get; set; } = new HTXSocketOptions + internal static HTXSocketOptions Default { get; set; } = new HTXSocketOptions { Environment = HTXEnvironment.Live, SocketSubscriptionsCombineTarget = 10 }; + /// + /// ctor + /// + public HTXSocketOptions() + { + Default?.Set(this); + } + /// /// Broker id /// @@ -31,13 +39,13 @@ public class HTXSocketOptions : SocketExchangeOptions /// public SocketApiOptions UsdtMarginSwapOptions { get; private set; } = new SocketApiOptions(); - internal HTXSocketOptions Copy() + internal HTXSocketOptions Set(HTXSocketOptions targetOptions) { - var options = Copy(); - options.BrokerId = BrokerId; - options.SpotOptions = SpotOptions.Copy(); - options.UsdtMarginSwapOptions = UsdtMarginSwapOptions.Copy(); - return options; + targetOptions = base.Set(targetOptions); + targetOptions.BrokerId = BrokerId; + targetOptions.SpotOptions = SpotOptions.Set(targetOptions.SpotOptions); + targetOptions.UsdtMarginSwapOptions = UsdtMarginSwapOptions.Set(targetOptions.UsdtMarginSwapOptions); + return targetOptions; } } } diff --git a/docs/index.html b/docs/index.html index 08a0e8eb..b633de2e 100644 --- a/docs/index.html +++ b/docs/index.html @@ -190,8 +190,14 @@

API Access

HTX.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.AddHTX(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.AddHTX(builder.Configuration.GetSection("HTX"));
+		  
+// OR
+		  
+ builder.Services.AddHTX(options => {
+  // Configure options in code
   options.ApiCredentials = new ApiCredentials("APIKEY", "APISECRET");
 });