From 4b32e7e32a08b7ef7f0a4bca56a393ddb3d8bfe3 Mon Sep 17 00:00:00 2001 From: Jkorf Date: Mon, 18 Nov 2024 14:38:31 +0100 Subject: [PATCH 1/2] wip --- .../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 | 85 ++++++++++--- Coinbase.Net/CoinbaseEnvironment.cs | 20 +++ .../ServiceCollectionExtensions.cs | 117 ++++++++++++++---- .../Objects/Options/CoinbaseOptions.cs | 39 ++++++ .../Objects/Options/CoinbaseRestOptions.cs | 21 ++-- .../Objects/Options/CoinbaseSocketOptions.cs | 21 +++- 11 files changed, 378 insertions(+), 88 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..535ec9a 100644 --- a/Coinbase.Net/Coinbase.Net.csproj +++ b/Coinbase.Net/Coinbase.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/Coinbase.Net/Coinbase.Net.xml b/Coinbase.Net/Coinbase.Net.xml index 4e025d4..e24818b 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 @@ -6103,6 +6107,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 +6162,11 @@ Default options for new clients + + + ctor + + Advanced Trade API options @@ -6143,6 +6182,11 @@ Default options for new clients + + + ctor + + Advanced Trade API options @@ -6246,15 +6290,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/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; } } } From b10eb9d1277e32e67a087b3045ede388d4670a6e Mon Sep 17 00:00:00 2001 From: Jkorf Date: Tue, 19 Nov 2024 12:59:21 +0100 Subject: [PATCH 2/2] updated CryptoExchange ref --- Coinbase.Net/Coinbase.Net.csproj | 6 ++---- Coinbase.Net/Coinbase.Net.xml | 10 ++++++++++ Coinbase.Net/CoinbaseExchange.cs | 10 ++++++++++ docs/index.html | 12 +++++++++--- 4 files changed, 31 insertions(+), 7 deletions(-) diff --git a/Coinbase.Net/Coinbase.Net.csproj b/Coinbase.Net/Coinbase.Net.csproj index 535ec9a..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,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/Coinbase.Net/Coinbase.Net.xml b/Coinbase.Net/Coinbase.Net.xml index e24818b..2a05c49 100644 --- a/Coinbase.Net/Coinbase.Net.xml +++ b/Coinbase.Net/Coinbase.Net.xml @@ -426,6 +426,16 @@ Exchange name + + + Exchange name + + + + + Url to exchange image + + Url to the main website 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/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.