From ad95cfe85712fef26c1ed1aab48c0b0752960f7d Mon Sep 17 00:00:00 2001 From: Jan Korf Date: Tue, 19 Nov 2024 13:36:11 +0100 Subject: [PATCH] Client Configuration (#3) 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 CoinbaseExchange class Updated client constructors to accept IOptions from DI Removed redundant CoinbaseSocketClient constructor --- .../CoinbaseRestClientTests.cs | 104 ++++++++++++++++ .../CoinbaseRestIntegrationTests.cs | 11 +- Coinbase.Net/Clients/CoinbaseRestClient.cs | 19 ++- Coinbase.Net/Clients/CoinbaseSocketClient.cs | 25 ++-- Coinbase.Net/Coinbase.Net.csproj | 4 +- Coinbase.Net/Coinbase.Net.xml | 95 +++++++++++--- Coinbase.Net/CoinbaseEnvironment.cs | 20 +++ Coinbase.Net/CoinbaseExchange.cs | 10 ++ .../ServiceCollectionExtensions.cs | 117 ++++++++++++++---- .../Objects/Options/CoinbaseOptions.cs | 39 ++++++ .../Objects/Options/CoinbaseRestOptions.cs | 21 ++-- .../Objects/Options/CoinbaseSocketOptions.cs | 21 +++- docs/index.html | 12 +- 13 files changed, 406 insertions(+), 92 deletions(-) create mode 100644 Coinbase.Net/Objects/Options/CoinbaseOptions.cs diff --git a/Coinbase.Net.UnitTests/CoinbaseRestClientTests.cs b/Coinbase.Net.UnitTests/CoinbaseRestClientTests.cs index 7feba87..ee46a69 100644 --- a/Coinbase.Net.UnitTests/CoinbaseRestClientTests.cs +++ b/Coinbase.Net.UnitTests/CoinbaseRestClientTests.cs @@ -5,6 +5,10 @@ using System.Collections.Generic; using System.Net.Http; using Coinbase.Net.Clients; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using CryptoExchange.Net.Objects; +using Coinbase.Net.Interfaces.Clients; namespace Coinbase.Net.UnitTests { @@ -17,5 +21,105 @@ public void CheckInterfaces() CryptoExchange.Net.Testing.TestHelpers.CheckForMissingRestInterfaces(); CryptoExchange.Net.Testing.TestHelpers.CheckForMissingSocketInterfaces(); } + + [Test] + [TestCase(TradeEnvironmentNames.Live, "https://api.coinbase.com")] + [TestCase("", "https://api.coinbase.com")] + public void TestConstructorEnvironments(string environmentName, string expected) + { + var configuration = new ConfigurationBuilder() + .AddInMemoryCollection(new Dictionary + { + { "Coinbase:Environment:Name", environmentName }, + }).Build(); + + var collection = new ServiceCollection(); + collection.AddCoinbase(configuration.GetSection("Coinbase")); + var provider = collection.BuildServiceProvider(); + + var client = provider.GetRequiredService(); + + var address = client.AdvancedTradeApi.BaseAddress; + + Assert.That(address, Is.EqualTo(expected)); + } + + [Test] + public void TestConstructorNullEnvironment() + { + var configuration = new ConfigurationBuilder() + .AddInMemoryCollection(new Dictionary + { + { "Coinbase", null }, + }).Build(); + + var collection = new ServiceCollection(); + collection.AddCoinbase(configuration.GetSection("Coinbase")); + var provider = collection.BuildServiceProvider(); + + var client = provider.GetRequiredService(); + + var address = client.AdvancedTradeApi.BaseAddress; + + Assert.That(address, Is.EqualTo("https://api.coinbase.com")); + } + + [Test] + public void TestConstructorApiOverwriteEnvironment() + { + var configuration = new ConfigurationBuilder() + .AddInMemoryCollection(new Dictionary + { + { "Coinbase:Environment:Name", "test" }, + { "Coinbase:Rest:Environment:Name", "live" }, + }).Build(); + + var collection = new ServiceCollection(); + collection.AddCoinbase(configuration.GetSection("Coinbase")); + var provider = collection.BuildServiceProvider(); + + var client = provider.GetRequiredService(); + + var address = client.AdvancedTradeApi.BaseAddress; + + Assert.That(address, Is.EqualTo("https://api.coinbase.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.AddCoinbase(configuration); + var provider = collection.BuildServiceProvider(); + + var restClient = provider.GetRequiredService(); + var socketClient = provider.GetRequiredService(); + + Assert.That(((BaseApiClient)restClient.AdvancedTradeApi).OutputOriginalData, Is.True); + Assert.That(((BaseApiClient)socketClient.AdvancedTradeApi).OutputOriginalData, Is.False); + Assert.That(((BaseApiClient)restClient.AdvancedTradeApi).AuthenticationProvider.ApiKey, Is.EqualTo("123")); + Assert.That(((BaseApiClient)socketClient.AdvancedTradeApi).AuthenticationProvider.ApiKey, Is.EqualTo("456")); + Assert.That(((BaseApiClient)restClient.AdvancedTradeApi).ClientOptions.Proxy.Host, Is.EqualTo("host")); + Assert.That(((BaseApiClient)restClient.AdvancedTradeApi).ClientOptions.Proxy.Port, Is.EqualTo(80)); + Assert.That(((BaseApiClient)socketClient.AdvancedTradeApi).ClientOptions.Proxy.Host, Is.EqualTo("host2")); + Assert.That(((BaseApiClient)socketClient.AdvancedTradeApi).ClientOptions.Proxy.Port, Is.EqualTo(81)); + } } } diff --git a/Coinbase.Net.UnitTests/CoinbaseRestIntegrationTests.cs b/Coinbase.Net.UnitTests/CoinbaseRestIntegrationTests.cs index 3340c95..44dd1cd 100644 --- a/Coinbase.Net.UnitTests/CoinbaseRestIntegrationTests.cs +++ b/Coinbase.Net.UnitTests/CoinbaseRestIntegrationTests.cs @@ -1,6 +1,7 @@ using Coinbase.Net.Clients; using CryptoExchange.Net.Testing; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using NUnit.Framework; using System; using System.Diagnostics; @@ -25,12 +26,12 @@ public override CoinbaseRestClient GetClient(ILoggerFactory loggerFactory) var sec = Environment.GetEnvironmentVariable("APISECRET"); Authenticated = key != null && sec != null; - return new CoinbaseRestClient(null, loggerFactory, opts => + return new CoinbaseRestClient(null, loggerFactory, Options.Create(new Objects.Options.CoinbaseRestOptions { - opts.AutoTimestamp = false; - opts.OutputOriginalData = true; - opts.ApiCredentials = Authenticated ? new CryptoExchange.Net.Authentication.ApiCredentials(key, sec) : null; - }); + AutoTimestamp = false, + OutputOriginalData = true, + ApiCredentials = Authenticated ? new CryptoExchange.Net.Authentication.ApiCredentials(key, sec) : null + })); } [Test] diff --git a/Coinbase.Net/Clients/CoinbaseRestClient.cs b/Coinbase.Net/Clients/CoinbaseRestClient.cs index a640615..fda40cb 100644 --- a/Coinbase.Net/Clients/CoinbaseRestClient.cs +++ b/Coinbase.Net/Clients/CoinbaseRestClient.cs @@ -7,6 +7,7 @@ using CryptoExchange.Net.Clients; using Coinbase.Net.Interfaces.Clients.AdvancedTradeApi; using Coinbase.Net.Clients.AdvancedTradeApi; +using Microsoft.Extensions.Options; namespace Coinbase.Net.Clients { @@ -27,24 +28,22 @@ public class CoinbaseRestClient : BaseRestClient, ICoinbaseRestClient /// Create a new instance of the CoinbaseRestClient using provided options /// /// Option configuration delegate - public CoinbaseRestClient(Action? optionsDelegate = null) : this(null, null, optionsDelegate) + public CoinbaseRestClient(Action? optionsDelegate = null) + : this(null, null, Options.Create(ApplyOptionsDelegate(optionsDelegate))) { } /// /// Create a new instance of the CoinbaseRestClient using provided options /// - /// Option configuration delegate + /// Option configuration /// The logger factory /// Http client for this client - public CoinbaseRestClient(HttpClient? httpClient, ILoggerFactory? loggerFactory, Action? optionsDelegate = null) : base(loggerFactory, "Coinbase") + public CoinbaseRestClient(HttpClient? httpClient, ILoggerFactory? loggerFactory, IOptions options) : base(loggerFactory, "Coinbase") { - var options = CoinbaseRestOptions.Default.Copy(); - if (optionsDelegate != null) - optionsDelegate(options); - Initialize(options); + Initialize(options.Value); - AdvancedTradeApi = AddApiClient(new CoinbaseRestClientAdvancedTradeApi(this, _logger, httpClient, options)); + AdvancedTradeApi = AddApiClient(new CoinbaseRestClientAdvancedTradeApi(this, _logger, httpClient, options.Value)); } #endregion @@ -55,9 +54,7 @@ public CoinbaseRestClient(HttpClient? httpClient, ILoggerFactory? loggerFactory, /// Option configuration delegate public static void SetDefaultOptions(Action optionsDelegate) { - var options = CoinbaseRestOptions.Default.Copy(); - optionsDelegate(options); - CoinbaseRestOptions.Default = options; + CoinbaseRestOptions.Default = ApplyOptionsDelegate(optionsDelegate); } /// diff --git a/Coinbase.Net/Clients/CoinbaseSocketClient.cs b/Coinbase.Net/Clients/CoinbaseSocketClient.cs index 28ffcb6..2b66643 100644 --- a/Coinbase.Net/Clients/CoinbaseSocketClient.cs +++ b/Coinbase.Net/Clients/CoinbaseSocketClient.cs @@ -6,6 +6,7 @@ using Coinbase.Net.Objects.Options; using Coinbase.Net.Interfaces.Clients.AdvancedTradeApi; using Coinbase.Net.Clients.AdvancedTradeApi; +using Microsoft.Extensions.Options; namespace Coinbase.Net.Clients { @@ -23,19 +24,13 @@ public class CoinbaseSocketClient : BaseSocketClient, ICoinbaseSocketClient #endregion #region constructor/destructor - /// - /// Create a new instance of CoinbaseSocketClient - /// - /// The logger factory - public CoinbaseSocketClient(ILoggerFactory? loggerFactory = null) : this((x) => { }, loggerFactory) - { - } /// /// Create a new instance of CoinbaseSocketClient /// /// Option configuration delegate - public CoinbaseSocketClient(Action optionsDelegate) : this(optionsDelegate, null) + public CoinbaseSocketClient(Action? optionsDelegate = null) + : this(Options.Create(ApplyOptionsDelegate(optionsDelegate)), null) { } @@ -43,14 +38,12 @@ public CoinbaseSocketClient(Action optionsDelegate) : thi /// Create a new instance of CoinbaseSocketClient /// /// The logger factory - /// Option configuration delegate - public CoinbaseSocketClient(Action? optionsDelegate, ILoggerFactory? loggerFactory = null) : base(loggerFactory, "Coinbase") + /// Option configuration + public CoinbaseSocketClient(IOptions options, ILoggerFactory? loggerFactory = null) : base(loggerFactory, "Coinbase") { - var options = CoinbaseSocketOptions.Default.Copy(); - optionsDelegate?.Invoke(options); - Initialize(options); + Initialize(options.Value); - AdvancedTradeApi = AddApiClient(new CoinbaseSocketClientAdvancedTradeApi(_logger, options)); + AdvancedTradeApi = AddApiClient(new CoinbaseSocketClientAdvancedTradeApi(_logger, options.Value)); } #endregion @@ -60,9 +53,7 @@ public CoinbaseSocketClient(Action? optionsDelegate, ILog /// Option configuration delegate public static void SetDefaultOptions(Action optionsDelegate) { - var options = CoinbaseSocketOptions.Default.Copy(); - optionsDelegate(options); - CoinbaseSocketOptions.Default = options; + CoinbaseSocketOptions.Default = ApplyOptionsDelegate(optionsDelegate); } /// diff --git a/Coinbase.Net/Coinbase.Net.csproj b/Coinbase.Net/Coinbase.Net.csproj index ca57a07..17a425d 100644 --- a/Coinbase.Net/Coinbase.Net.csproj +++ b/Coinbase.Net/Coinbase.Net.csproj @@ -1,4 +1,4 @@ - + netstandard2.0;netstandard2.1 12.0 @@ -48,7 +48,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + all diff --git a/Coinbase.Net/Coinbase.Net.xml b/Coinbase.Net/Coinbase.Net.xml index 4e025d4..2a05c49 100644 --- a/Coinbase.Net/Coinbase.Net.xml +++ b/Coinbase.Net/Coinbase.Net.xml @@ -326,11 +326,11 @@ Option configuration delegate - + Create a new instance of the CoinbaseRestClient using provided options - Option configuration delegate + Option configuration The logger factory Http client for this client @@ -349,24 +349,18 @@ - - - Create a new instance of CoinbaseSocketClient - - The logger factory - Create a new instance of CoinbaseSocketClient Option configuration delegate - + Create a new instance of CoinbaseSocketClient The logger factory - Option configuration delegate + Option configuration @@ -397,6 +391,16 @@ Socket API address + + + ctor for DI, use for creating a custom environment + + + + + Get the Coinbase environment by name + + Live environment @@ -422,6 +426,16 @@ Exchange name + + + Exchange name + + + + + Url to exchange image + + Url to the main website @@ -6103,6 +6117,36 @@ Intraday trading setting value + + + Coinbase options + + + + + Rest client options + + + + + Socket client options + + + + + Trade environment. Contains info about URL's to use to connect to the API. Use `CoinbaseEnvironment` to swap environment, for example `Environment = CoinbaseEnvironment.Live` + + + + + The api credentials used for signing requests. + + + + + The DI service lifetime for the ICoinbaseSocketClient + + Options for the Coinbase SymbolOrderBook @@ -6128,6 +6172,11 @@ Default options for new clients + + + ctor + + Advanced Trade API options @@ -6143,6 +6192,11 @@ Default options for new clients + + + ctor + + Advanced Trade API options @@ -6246,15 +6300,26 @@ Extensions for DI - + + + Add services such as the ICoinbaseRestClient and ICoinbaseSocketClient. Configures the services based on the provided configuration. + + The service collection + The configuration(section) containing the options + + + - Add the ICoinbaseRestClient and ICoinbaseSocketClient to the sevice collection so they can be injected + Add services such as the ICoinbaseRestClient and ICoinbaseSocketClient. 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 ICoinbaseSocketClient for the service collection. Defaults to Singleton. + Set options for the Coinbase services + + + DEPRECATED; use instead + + diff --git a/Coinbase.Net/CoinbaseEnvironment.cs b/Coinbase.Net/CoinbaseEnvironment.cs index 6c72933..6215534 100644 --- a/Coinbase.Net/CoinbaseEnvironment.cs +++ b/Coinbase.Net/CoinbaseEnvironment.cs @@ -35,6 +35,26 @@ internal CoinbaseEnvironment( SocketClientPrivateAddress = streamAddressPrivate; } + /// + /// 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 CoinbaseEnvironment() : 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 Coinbase environment by name + /// + public static CoinbaseEnvironment? GetEnvironmentByName(string? name) + => name switch + { + TradeEnvironmentNames.Live => Live, + "" => Live, + null => Live, + _ => default + }; + /// /// Live environment /// diff --git a/Coinbase.Net/CoinbaseExchange.cs b/Coinbase.Net/CoinbaseExchange.cs index f5004db..1c59842 100644 --- a/Coinbase.Net/CoinbaseExchange.cs +++ b/Coinbase.Net/CoinbaseExchange.cs @@ -19,6 +19,16 @@ public static class CoinbaseExchange /// public static string ExchangeName => "Coinbase"; + /// + /// Exchange name + /// + public static string DisplayName => "Coinbase"; + + /// + /// Url to exchange image + /// + public static string ImageUrl { get; } = "https://raw.githubusercontent.com/JKorf/Coinbase.Net/master/Coinbase.Net/Icon/icon.png"; + /// /// Url to the main website /// diff --git a/Coinbase.Net/ExtensionMethods/ServiceCollectionExtensions.cs b/Coinbase.Net/ExtensionMethods/ServiceCollectionExtensions.cs index 077e7f5..761221f 100644 --- a/Coinbase.Net/ExtensionMethods/ServiceCollectionExtensions.cs +++ b/Coinbase.Net/ExtensionMethods/ServiceCollectionExtensions.cs @@ -10,6 +10,9 @@ using Coinbase.Net.SymbolOrderBooks; using CryptoExchange.Net; using Coinbase.Net; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Microsoft.Extensions.Configuration; namespace Microsoft.Extensions.DependencyInjection { @@ -19,46 +22,112 @@ namespace Microsoft.Extensions.DependencyInjection public static class ServiceCollectionExtensions { /// - /// Add the ICoinbaseRestClient and ICoinbaseSocketClient to the sevice collection so they can be injected + /// Add services such as the ICoinbaseRestClient and ICoinbaseSocketClient. 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 ICoinbaseSocketClient for the service collection. Defaults to Singleton. + /// The configuration(section) containing the options /// public static IServiceCollection AddCoinbase( this IServiceCollection services, - Action? defaultRestOptionsDelegate = null, - Action? defaultSocketOptionsDelegate = null, - ServiceLifetime? socketClientLifeTime = null) + IConfiguration configuration) { - var restOptions = CoinbaseRestOptions.Default.Copy(); + var options = new CoinbaseOptions(); + // Reset environment so we know if theyre overriden + options.Rest.Environment = null!; + options.Socket.Environment = null!; + configuration.Bind(options); - if (defaultRestOptionsDelegate != null) - { - defaultRestOptionsDelegate(restOptions); - CoinbaseRestClient.SetDefaultOptions(defaultRestOptionsDelegate); - } + if (options.Rest == null || options.Socket == null) + throw new ArgumentException("Options null"); - if (defaultSocketOptionsDelegate != null) - CoinbaseSocketClient.SetDefaultOptions(defaultSocketOptionsDelegate); + var restEnvName = options.Rest.Environment?.Name ?? options.Environment?.Name ?? CoinbaseEnvironment.Live.Name; + var socketEnvName = options.Socket.Environment?.Name ?? options.Environment?.Name ?? CoinbaseEnvironment.Live.Name; + options.Rest.Environment = CoinbaseEnvironment.GetEnvironmentByName(restEnvName) ?? options.Rest.Environment!; + options.Rest.ApiCredentials = options.Rest.ApiCredentials ?? options.ApiCredentials; + options.Socket.Environment = CoinbaseEnvironment.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 AddCoinbaseCore(services, options.SocketClientLifeTime); + } + + /// + /// Add services such as the ICoinbaseRestClient and ICoinbaseSocketClient. Services will be configured based on the provided options. + /// + /// The service collection + /// Set options for the Coinbase services + /// + public static IServiceCollection AddCoinbase( + this IServiceCollection services, + Action? optionsDelegate = null) + { + var options = new CoinbaseOptions(); + // 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 ?? CoinbaseEnvironment.Live; + options.Rest.ApiCredentials = options.Rest.ApiCredentials ?? options.ApiCredentials; + options.Socket.Environment = options.Socket.Environment ?? options.Environment ?? CoinbaseEnvironment.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 AddCoinbaseCore(services, options.SocketClientLifeTime); + } + + /// + /// DEPRECATED; use instead + /// + public static IServiceCollection AddCoinbase( + this IServiceCollection services, + Action restDelegate, + Action? socketDelegate = null, + ServiceLifetime? socketClientLifeTime = null) + { + services.Configure((x) => { restDelegate?.Invoke(x); }); + services.Configure((x) => { socketDelegate?.Invoke(x); }); + + return AddCoinbaseCore(services, socketClientLifeTime); + } + + private static IServiceCollection AddCoinbaseCore( + this IServiceCollection services, + ServiceLifetime? socketClientLifeTime = null) + { + services.AddHttpClient((client, serviceProvider) => { + var options = serviceProvider.GetRequiredService>().Value; + client.Timeout = options.RequestTimeout; + return new CoinbaseRestClient(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(ICoinbaseSocketClient), x => { return new CoinbaseSocketClient(x.GetRequiredService>(), x.GetRequiredService()); }, socketClientLifeTime ?? ServiceLifetime.Singleton)); services.AddTransient(); services.AddSingleton(); @@ -68,10 +137,6 @@ public static IServiceCollection AddCoinbase( services.RegisterSharedRestInterfaces(x => x.GetRequiredService().AdvancedTradeApi.SharedClient); services.RegisterSharedSocketInterfaces(x => x.GetRequiredService().AdvancedTradeApi.SharedClient); - if (socketClientLifeTime == null) - services.AddSingleton(); - else - services.Add(new ServiceDescriptor(typeof(ICoinbaseSocketClient), typeof(CoinbaseSocketClient), socketClientLifeTime.Value)); return services; } } diff --git a/Coinbase.Net/Objects/Options/CoinbaseOptions.cs b/Coinbase.Net/Objects/Options/CoinbaseOptions.cs new file mode 100644 index 0000000..f171d1e --- /dev/null +++ b/Coinbase.Net/Objects/Options/CoinbaseOptions.cs @@ -0,0 +1,39 @@ +using CryptoExchange.Net.Authentication; +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Coinbase.Net.Objects.Options +{ + /// + /// Coinbase options + /// + public class CoinbaseOptions + { + /// + /// Rest client options + /// + public CoinbaseRestOptions Rest { get; set; } = new CoinbaseRestOptions(); + + /// + /// Socket client options + /// + public CoinbaseSocketOptions Socket { get; set; } = new CoinbaseSocketOptions(); + + /// + /// Trade environment. Contains info about URL's to use to connect to the API. Use `CoinbaseEnvironment` to swap environment, for example `Environment = CoinbaseEnvironment.Live` + /// + public CoinbaseEnvironment? Environment { get; set; } + + /// + /// The api credentials used for signing requests. + /// + public ApiCredentials? ApiCredentials { get; set; } + + /// + /// The DI service lifetime for the ICoinbaseSocketClient + /// + public ServiceLifetime? SocketClientLifeTime { get; set; } + } +} diff --git a/Coinbase.Net/Objects/Options/CoinbaseRestOptions.cs b/Coinbase.Net/Objects/Options/CoinbaseRestOptions.cs index ed8a370..4bac4a1 100644 --- a/Coinbase.Net/Objects/Options/CoinbaseRestOptions.cs +++ b/Coinbase.Net/Objects/Options/CoinbaseRestOptions.cs @@ -10,23 +10,30 @@ public class CoinbaseRestOptions : RestExchangeOptions /// /// Default options for new clients /// - public static CoinbaseRestOptions Default { get; set; } = new CoinbaseRestOptions() + internal static CoinbaseRestOptions Default { get; set; } = new CoinbaseRestOptions() { Environment = CoinbaseEnvironment.Live, AutoTimestamp = true }; - /// + /// + /// ctor + /// + public CoinbaseRestOptions() + { + Default?.Set(this); + } + + /// /// Advanced Trade API options /// public RestApiOptions AdvancedTradeOptions { get; private set; } = new RestApiOptions(); - - internal CoinbaseRestOptions Copy() + internal CoinbaseRestOptions Set(CoinbaseRestOptions targetOptions) { - var options = Copy(); - options.AdvancedTradeOptions = AdvancedTradeOptions.Copy(); - return options; + targetOptions = base.Set(targetOptions); + targetOptions.AdvancedTradeOptions = AdvancedTradeOptions.Set(targetOptions.AdvancedTradeOptions); + return targetOptions; } } } diff --git a/Coinbase.Net/Objects/Options/CoinbaseSocketOptions.cs b/Coinbase.Net/Objects/Options/CoinbaseSocketOptions.cs index ef94e5a..b76c21a 100644 --- a/Coinbase.Net/Objects/Options/CoinbaseSocketOptions.cs +++ b/Coinbase.Net/Objects/Options/CoinbaseSocketOptions.cs @@ -10,22 +10,31 @@ public class CoinbaseSocketOptions : SocketExchangeOptions /// /// Default options for new clients /// - public static CoinbaseSocketOptions Default { get; set; } = new CoinbaseSocketOptions() + internal static CoinbaseSocketOptions Default { get; set; } = new CoinbaseSocketOptions() { Environment = CoinbaseEnvironment.Live, SocketSubscriptionsCombineTarget = 10 }; - /// + /// + /// ctor + /// + public CoinbaseSocketOptions() + { + Default?.Set(this); + } + + /// /// Advanced Trade API options /// public SocketApiOptions AdvancedTradeOptions { get; private set; } = new SocketApiOptions(); - internal CoinbaseSocketOptions Copy() + + internal CoinbaseSocketOptions Set(CoinbaseSocketOptions targetOptions) { - var options = Copy(); - options.AdvancedTradeOptions = AdvancedTradeOptions.Copy(); - return options; + targetOptions = base.Set(targetOptions); + targetOptions.AdvancedTradeOptions = AdvancedTradeOptions.Set(targetOptions.AdvancedTradeOptions); + return targetOptions; } } } diff --git a/docs/index.html b/docs/index.html index 2776af3..1b9eb54 100644 --- a/docs/index.html +++ b/docs/index.html @@ -189,9 +189,15 @@

API Access

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

The ICoinbaseRestClient and ICoinbaseSocketClient can then be injected.