diff --git a/CryptoExchange.Net.UnitTests/OptionsTests.cs b/CryptoExchange.Net.UnitTests/OptionsTests.cs index 35d8905..59cb299 100644 --- a/CryptoExchange.Net.UnitTests/OptionsTests.cs +++ b/CryptoExchange.Net.UnitTests/OptionsTests.cs @@ -1,4 +1,5 @@ using CryptoExchange.Net.Authentication; +using CryptoExchange.Net.Objects; using CryptoExchange.Net.Objects.Options; using CryptoExchange.Net.UnitTests.TestImplementations; using NUnit.Framework; @@ -54,6 +55,63 @@ namespace CryptoExchange.Net.UnitTests Assert.That(options.ApiCredentials.Secret == "456"); } + [Test] + public void TestSetOptionsRest() + { + var client = new TestRestClient(); + client.SetOptions(new UpdateOptions + { + RequestTimeout = TimeSpan.FromSeconds(2), + Proxy = new ApiProxy("http://testproxy", 1234) + }); + + Assert.That(client.Api1.ClientOptions.Proxy, Is.Not.Null); + Assert.That(client.Api1.ClientOptions.Proxy.Host, Is.EqualTo("http://testproxy")); + Assert.That(client.Api1.ClientOptions.Proxy.Port, Is.EqualTo(1234)); + Assert.That(client.Api1.ClientOptions.RequestTimeout, Is.EqualTo(TimeSpan.FromSeconds(2))); + } + + [Test] + public void TestSetOptionsRestWithCredentials() + { + var client = new TestRestClient(); + client.SetOptions(new UpdateOptions + { + ApiCredentials = new HMACCredential("123", "456"), + RequestTimeout = TimeSpan.FromSeconds(2), + Proxy = new ApiProxy("http://testproxy", 1234) + }); + + Assert.That(client.Api1.ApiCredentials, Is.Not.Null); + Assert.That(client.Api1.ApiCredentials.Key, Is.EqualTo("123")); + Assert.That(client.Api1.ClientOptions.Proxy, Is.Not.Null); + Assert.That(client.Api1.ClientOptions.Proxy.Host, Is.EqualTo("http://testproxy")); + Assert.That(client.Api1.ClientOptions.Proxy.Port, Is.EqualTo(1234)); + Assert.That(client.Api1.ClientOptions.RequestTimeout, Is.EqualTo(TimeSpan.FromSeconds(2))); + } + + [Test] + public void TestWhenUpdatingSettingsExistingClientsAreNotAffected() + { + TestClientOptions.Default = new TestClientOptions + { + ApiCredentials = new HMACCredential("111", "222"), + RequestTimeout = TimeSpan.FromSeconds(1), + }; + + var client1 = new TestRestClient(); + + Assert.That(client1.ClientOptions.RequestTimeout, Is.EqualTo(TimeSpan.FromSeconds(1))); + Assert.That(client1.ClientOptions.ApiCredentials.Key, Is.EqualTo("111")); + + TestClientOptions.Default.ApiCredentials = new HMACCredential("333", "444"); + TestClientOptions.Default.RequestTimeout = TimeSpan.FromSeconds(2); + + var client2 = new TestRestClient(); + + Assert.That(client2.ClientOptions.RequestTimeout, Is.EqualTo(TimeSpan.FromSeconds(2))); + Assert.That(client2.ClientOptions.ApiCredentials.Key, Is.EqualTo("333")); + } } public class TestClientOptions: RestExchangeOptions diff --git a/CryptoExchange.Net.UnitTests/TestImplementations/TestRestClient.cs b/CryptoExchange.Net.UnitTests/TestImplementations/TestRestClient.cs index 5e90269..487e825 100644 --- a/CryptoExchange.Net.UnitTests/TestImplementations/TestRestClient.cs +++ b/CryptoExchange.Net.UnitTests/TestImplementations/TestRestClient.cs @@ -23,7 +23,7 @@ using CryptoExchange.Net.Converters.MessageParsing.DynamicConverters; namespace CryptoExchange.Net.UnitTests.TestImplementations { - public class TestRestClient: BaseRestClient + public class TestRestClient: BaseRestClient { public TestRestApi1Client Api1 { get; } public TestRestApi2Client Api2 { get; } @@ -37,8 +37,8 @@ namespace CryptoExchange.Net.UnitTests.TestImplementations { Initialize(options.Value); - Api1 = new TestRestApi1Client(options.Value); - Api2 = new TestRestApi2Client(options.Value); + Api1 = AddApiClient(new TestRestApi1Client(options.Value)); + Api2 = AddApiClient(new TestRestApi2Client(options.Value)); } public void SetResponse(string responseData, out IRequest requestObj) diff --git a/CryptoExchange.Net/Clients/BaseRestClient.cs b/CryptoExchange.Net/Clients/BaseRestClient.cs index 8107770..f1a505a 100644 --- a/CryptoExchange.Net/Clients/BaseRestClient.cs +++ b/CryptoExchange.Net/Clients/BaseRestClient.cs @@ -14,6 +14,11 @@ namespace CryptoExchange.Net.Clients /// public abstract class BaseRestClient : BaseClient, IRestClient { + /// + /// Api clients in this client + /// + internal new List ApiClients => base.ApiClients.OfType().ToList(); + /// public int TotalRequestsMade => ApiClients.OfType().Sum(s => s.TotalRequestsMade); @@ -29,6 +34,14 @@ namespace CryptoExchange.Net.Clients LibraryHelpers.StaticLogger = loggerFactory?.CreateLogger("CryptoExchange"); } + /// + /// Update options + /// + public virtual void SetOptions(UpdateOptions options) + { + foreach (var apiClient in ApiClients) + apiClient.SetOptions(options); + } } /// @@ -41,6 +54,11 @@ namespace CryptoExchange.Net.Clients /// internal new List> ApiClients => base.ApiClients.OfType>().ToList(); + /// + /// Provided client options + /// + public new RestExchangeOptions ClientOptions => (RestExchangeOptions)base.ClientOptions; + /// /// ctor /// diff --git a/CryptoExchange.Net/Clients/BaseSocketClient.cs b/CryptoExchange.Net/Clients/BaseSocketClient.cs index 8974144..911cba0 100644 --- a/CryptoExchange.Net/Clients/BaseSocketClient.cs +++ b/CryptoExchange.Net/Clients/BaseSocketClient.cs @@ -21,6 +21,11 @@ namespace CryptoExchange.Net.Clients { #region fields + /// + /// Api clients in this client + /// + internal new List ApiClients => base.ApiClients.OfType().ToList(); + /// /// If client is disposing /// @@ -135,6 +140,15 @@ namespace CryptoExchange.Net.Clients return result; } + + /// + /// Update options + /// + public virtual void SetOptions(UpdateOptions options) + { + foreach (var apiClient in ApiClients) + apiClient.SetOptions(options); + } } /// @@ -147,6 +161,11 @@ namespace CryptoExchange.Net.Clients /// internal new List> ApiClients => base.ApiClients.OfType>().ToList(); + /// + /// Provided client options + /// + public new SocketExchangeOptions ClientOptions => (SocketExchangeOptions)base.ClientOptions; + /// /// ctor /// diff --git a/CryptoExchange.Net/Clients/RestApiClient.cs b/CryptoExchange.Net/Clients/RestApiClient.cs index bbcc7d8..498af67 100644 --- a/CryptoExchange.Net/Clients/RestApiClient.cs +++ b/CryptoExchange.Net/Clients/RestApiClient.cs @@ -819,6 +819,16 @@ namespace CryptoExchange.Net.Clients && definition.Method == HttpMethod.Get && !definition.PreventCaching; + + /// + public virtual void SetOptions(UpdateOptions options) + { + _proxyConfigured = options.Proxy != null; + ClientOptions.Proxy = options.Proxy; + ClientOptions.RequestTimeout = options.RequestTimeout ?? ClientOptions.RequestTimeout; + + RequestFactory.UpdateSettings(options.Proxy, options.RequestTimeout ?? ClientOptions.RequestTimeout, ClientOptions.HttpKeepAliveInterval); + } } /// @@ -890,12 +900,9 @@ namespace CryptoExchange.Net.Clients /// public virtual void SetOptions(UpdateOptions options) { - _proxyConfigured = options.Proxy != null; - ClientOptions.Proxy = options.Proxy; - ClientOptions.RequestTimeout = options.RequestTimeout ?? ClientOptions.RequestTimeout; + base.SetOptions(options); ApiCredentials = (TApiCredentials?)options.ApiCredentials?.Copy() ?? ApiCredentials; - RequestFactory.UpdateSettings(options.Proxy, options.RequestTimeout ?? ClientOptions.RequestTimeout, ClientOptions.HttpKeepAliveInterval); } } diff --git a/CryptoExchange.Net/Clients/SocketApiClient.cs b/CryptoExchange.Net/Clients/SocketApiClient.cs index 428a5d9..f057657 100644 --- a/CryptoExchange.Net/Clients/SocketApiClient.cs +++ b/CryptoExchange.Net/Clients/SocketApiClient.cs @@ -1035,6 +1035,28 @@ namespace CryptoExchange.Net.Clients /// /// public abstract ISocketMessageHandler CreateMessageConverter(WebSocketMessageType messageType); + + /// + public virtual void SetOptions(UpdateOptions options) + { + var previousProxyIsSet = _proxyConfigured; + + ClientOptions.Proxy = options.Proxy; + ClientOptions.RequestTimeout = options.RequestTimeout ?? ClientOptions.RequestTimeout; + + _proxyConfigured = options.Proxy != null; + if ((!previousProxyIsSet && options.Proxy == null) + || _socketConnections.IsEmpty) + { + return; + } + + _logger.LogInformation("Reconnecting websockets to apply proxy"); + + // Update proxy, also triggers reconnect + foreach (var connection in _socketConnections) + _ = connection.Value.UpdateProxy(options.Proxy); + } } /// @@ -1102,25 +1124,7 @@ namespace CryptoExchange.Net.Clients /// public virtual void SetOptions(UpdateOptions options) { - var previousProxyIsSet = _proxyConfigured; - - ClientOptions.Proxy = options.Proxy; - ClientOptions.RequestTimeout = options.RequestTimeout ?? ClientOptions.RequestTimeout; - - ApiCredentials = (TApiCredentials?)options.ApiCredentials?.Copy() ?? ApiCredentials; - - _proxyConfigured = options.Proxy != null; - if ((!previousProxyIsSet && options.Proxy == null) - || _socketConnections.IsEmpty) - { - return; - } - - _logger.LogInformation("Reconnecting websockets to apply proxy"); - - // Update proxy, also triggers reconnect - foreach (var connection in _socketConnections) - _ = connection.Value.UpdateProxy(options.Proxy); + base.SetOptions(options); } } diff --git a/CryptoExchange.Net/Interfaces/Clients/IRestClient.cs b/CryptoExchange.Net/Interfaces/Clients/IRestClient.cs index a6b029b..98d620c 100644 --- a/CryptoExchange.Net/Interfaces/Clients/IRestClient.cs +++ b/CryptoExchange.Net/Interfaces/Clients/IRestClient.cs @@ -28,6 +28,12 @@ namespace CryptoExchange.Net.Interfaces.Clients /// Whether client is disposed /// bool Disposed { get; } + + /// + /// Update specific options + /// + /// Options to update. Only specific options are changeable after the client has been created + void SetOptions(UpdateOptions options); } /// diff --git a/CryptoExchange.Net/Interfaces/Clients/ISocketClient.cs b/CryptoExchange.Net/Interfaces/Clients/ISocketClient.cs index cacd534..a3dabc6 100644 --- a/CryptoExchange.Net/Interfaces/Clients/ISocketClient.cs +++ b/CryptoExchange.Net/Interfaces/Clients/ISocketClient.cs @@ -60,6 +60,12 @@ namespace CryptoExchange.Net.Interfaces.Clients /// /// Task UnsubscribeAllAsync(); + + /// + /// Update specific options + /// + /// Options to update. Only specific options are changeable after the client has been created + void SetOptions(UpdateOptions options); } /// diff --git a/CryptoExchange.Net/Objects/Options/UpdateOptions.cs b/CryptoExchange.Net/Objects/Options/UpdateOptions.cs index 7246c0f..eb7be4e 100644 --- a/CryptoExchange.Net/Objects/Options/UpdateOptions.cs +++ b/CryptoExchange.Net/Objects/Options/UpdateOptions.cs @@ -6,19 +6,27 @@ namespace CryptoExchange.Net.Objects.Options /// /// Options to update /// - public class UpdateOptions where TApiCredentials : ApiCredentials + public class UpdateOptions { /// /// Proxy setting. Note that if this is not provided any previously set proxy will be reset /// public ApiProxy? Proxy { get; set; } /// - /// Api credentials - /// - public TApiCredentials? ApiCredentials { get; set; } - /// /// Request timeout /// public TimeSpan? RequestTimeout { get; set; } } + + /// + /// Options to update + /// + public class UpdateOptions: UpdateOptions + where TApiCredentials : ApiCredentials + { + /// + /// Api credentials + /// + public TApiCredentials? ApiCredentials { get; set; } + } }