mirror of
https://github.com/JKorf/CryptoExchange.Net
synced 2025-06-06 15:36:30 +00:00
Client Configuration (#219)
Added support for IOptions injection, allowing options to be read from IConfiguration Small refactor on client options internals Updated HttpClient to be static field to be
This commit is contained in:
parent
48797038be
commit
7d7bc35869
@ -100,6 +100,10 @@ namespace CryptoExchange.Net.UnitTests
|
||||
Assert.That(authProvider1.GetSecret() == "222");
|
||||
Assert.That(authProvider2.GetKey() == "123");
|
||||
Assert.That(authProvider2.GetSecret() == "456");
|
||||
|
||||
// Cleanup static values
|
||||
TestClientOptions.Default.ApiCredentials = null;
|
||||
TestClientOptions.Default.Api1Options.ApiCredentials = null;
|
||||
}
|
||||
|
||||
[Test]
|
||||
@ -121,6 +125,10 @@ namespace CryptoExchange.Net.UnitTests
|
||||
Assert.That(authProvider2.GetKey() == "123");
|
||||
Assert.That(authProvider2.GetSecret() == "456");
|
||||
Assert.That(client.Api2.BaseAddress == "https://localhost:123");
|
||||
|
||||
// Cleanup static values
|
||||
TestClientOptions.Default.ApiCredentials = null;
|
||||
TestClientOptions.Default.Api1Options.ApiCredentials = null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -134,6 +142,14 @@ namespace CryptoExchange.Net.UnitTests
|
||||
Environment = new TestEnvironment("test", "https://test.com")
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public TestClientOptions()
|
||||
{
|
||||
Default?.Set(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The default receive window for requests
|
||||
/// </summary>
|
||||
@ -143,12 +159,12 @@ namespace CryptoExchange.Net.UnitTests
|
||||
|
||||
public RestApiOptions Api2Options { get; set; } = new RestApiOptions();
|
||||
|
||||
internal TestClientOptions Copy()
|
||||
internal TestClientOptions Set(TestClientOptions targetOptions)
|
||||
{
|
||||
var options = Copy<TestClientOptions>();
|
||||
options.Api1Options = Api1Options.Copy<RestApiOptions>();
|
||||
options.Api2Options = Api2Options.Copy<RestApiOptions>();
|
||||
return options;
|
||||
targetOptions = base.Set<TestClientOptions>(targetOptions);
|
||||
targetOptions.Api1Options = Api1Options.Set(targetOptions.Api1Options);
|
||||
targetOptions.Api2Options = Api2Options.Set(targetOptions.Api2Options);
|
||||
return targetOptions;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ namespace CryptoExchange.Net.UnitTests
|
||||
|
||||
public TestBaseClient(): base(null, "Test")
|
||||
{
|
||||
var options = TestClientOptions.Default.Copy();
|
||||
var options = new TestClientOptions();
|
||||
Initialize(options);
|
||||
SubClient = AddApiClient(new TestSubClient(options, new RestApiOptions()));
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ using CryptoExchange.Net.Objects.Options;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using CryptoExchange.Net.Clients;
|
||||
using CryptoExchange.Net.SharedApis;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace CryptoExchange.Net.UnitTests.TestImplementations
|
||||
{
|
||||
@ -24,22 +25,17 @@ namespace CryptoExchange.Net.UnitTests.TestImplementations
|
||||
public TestRestApi1Client Api1 { get; }
|
||||
public TestRestApi2Client Api2 { get; }
|
||||
|
||||
public TestRestClient(Action<TestClientOptions> optionsFunc) : this(optionsFunc, null)
|
||||
public TestRestClient(Action<TestClientOptions>? optionsDelegate = null)
|
||||
: this(null, null, Options.Create(ApplyOptionsDelegate(optionsDelegate)))
|
||||
{
|
||||
}
|
||||
|
||||
public TestRestClient(ILoggerFactory loggerFactory = null, HttpClient httpClient = null) : this((x) => { }, httpClient, loggerFactory)
|
||||
public TestRestClient(HttpClient? httpClient, ILoggerFactory? loggerFactory, IOptions<TestClientOptions> options) : base(loggerFactory, "Test")
|
||||
{
|
||||
}
|
||||
Initialize(options.Value);
|
||||
|
||||
public TestRestClient(Action<TestClientOptions> optionsFunc, HttpClient httpClient = null, ILoggerFactory loggerFactory = null) : base(loggerFactory, "Test")
|
||||
{
|
||||
var options = TestClientOptions.Default.Copy();
|
||||
optionsFunc(options);
|
||||
Initialize(options);
|
||||
|
||||
Api1 = new TestRestApi1Client(options);
|
||||
Api2 = new TestRestApi2Client(options);
|
||||
Api1 = new TestRestApi1Client(options.Value);
|
||||
Api2 = new TestRestApi2Client(options.Value);
|
||||
}
|
||||
|
||||
public void SetResponse(string responseData, out IRequest requestObj)
|
||||
|
@ -15,6 +15,7 @@ using Microsoft.Extensions.Logging;
|
||||
using Moq;
|
||||
using CryptoExchange.Net.Testing.Implementations;
|
||||
using CryptoExchange.Net.SharedApis;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace CryptoExchange.Net.UnitTests.TestImplementations
|
||||
{
|
||||
@ -22,25 +23,20 @@ namespace CryptoExchange.Net.UnitTests.TestImplementations
|
||||
{
|
||||
public TestSubSocketClient SubClient { get; }
|
||||
|
||||
public TestSocketClient(ILoggerFactory loggerFactory = null) : this((x) => { }, loggerFactory)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new instance of KucoinSocketClient
|
||||
/// </summary>
|
||||
/// <param name="optionsFunc">Configure the options to use for this client</param>
|
||||
public TestSocketClient(Action<TestSocketOptions> optionsFunc) : this(optionsFunc, null)
|
||||
public TestSocketClient(Action<TestSocketOptions>? optionsDelegate = null)
|
||||
: this(Options.Create(ApplyOptionsDelegate(optionsDelegate)), null)
|
||||
{
|
||||
}
|
||||
|
||||
public TestSocketClient(Action<TestSocketOptions> optionsFunc, ILoggerFactory loggerFactory = null) : base(loggerFactory, "Test")
|
||||
public TestSocketClient(IOptions<TestSocketOptions> options, ILoggerFactory? loggerFactory = null) : base(loggerFactory, "Test")
|
||||
{
|
||||
var options = TestSocketOptions.Default.Copy<TestSocketOptions>();
|
||||
optionsFunc(options);
|
||||
Initialize(options);
|
||||
Initialize(options.Value);
|
||||
|
||||
SubClient = AddApiClient(new TestSubSocketClient(options, options.SubOptions));
|
||||
SubClient = AddApiClient(new TestSubSocketClient(options.Value, options.Value.SubOptions));
|
||||
SubClient.SocketFactory = new Mock<IWebsocketFactory>().Object;
|
||||
Mock.Get(SubClient.SocketFactory).Setup(f => f.CreateWebsocket(It.IsAny<ILogger>(), It.IsAny<WebSocketParameters>())).Returns(new TestSocket("https://test.com"));
|
||||
}
|
||||
@ -70,7 +66,22 @@ namespace CryptoExchange.Net.UnitTests.TestImplementations
|
||||
Environment = new TestEnvironment("Live", "https://test.test")
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public TestSocketOptions()
|
||||
{
|
||||
Default?.Set(this);
|
||||
}
|
||||
|
||||
public SocketApiOptions SubOptions { get; set; } = new SocketApiOptions();
|
||||
|
||||
internal TestSocketOptions Set(TestSocketOptions targetOptions)
|
||||
{
|
||||
targetOptions = base.Set<TestSocketOptions>(targetOptions);
|
||||
targetOptions.SubOptions = SubOptions.Set(targetOptions.SubOptions);
|
||||
return targetOptions;
|
||||
}
|
||||
}
|
||||
|
||||
public class TestSubSocketClient : SocketApiClient
|
||||
|
@ -13,39 +13,30 @@ namespace CryptoExchange.Net.Authentication
|
||||
/// <summary>
|
||||
/// The api key / label to authenticate requests
|
||||
/// </summary>
|
||||
public string Key { get; }
|
||||
public string Key { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The api secret or private key to authenticate requests
|
||||
/// </summary>
|
||||
public string Secret { get; }
|
||||
public string Secret { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Type of the credentials
|
||||
/// </summary>
|
||||
public ApiCredentialsType CredentialType { get; }
|
||||
public ApiCredentialsType CredentialType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Create Api credentials providing an api key and secret for authentication
|
||||
/// </summary>
|
||||
/// <param name="key">The api key / label used for identification</param>
|
||||
/// <param name="secret">The api secret or private key used for signing</param>
|
||||
public ApiCredentials(string key, string secret) : this(key, secret, ApiCredentialsType.Hmac)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create Api credentials providing an api key and secret for authentication
|
||||
/// </summary>
|
||||
/// <param name="key">The api key / label used for identification</param>
|
||||
/// <param name="secret">The api secret or private key used for signing</param>
|
||||
/// <param name="credentialsType">The type of credentials</param>
|
||||
public ApiCredentials(string key, string secret, ApiCredentialsType credentialsType)
|
||||
/// <param name="credentialType">The type of credentials</param>
|
||||
public ApiCredentials(string key, string secret, ApiCredentialsType credentialType = ApiCredentialsType.Hmac)
|
||||
{
|
||||
if (string.IsNullOrEmpty(key) || string.IsNullOrEmpty(secret))
|
||||
throw new ArgumentException("Key and secret can't be null/empty");
|
||||
|
||||
CredentialType = credentialsType;
|
||||
CredentialType = credentialType;
|
||||
Key = key;
|
||||
Secret = secret;
|
||||
}
|
||||
@ -65,7 +56,7 @@ namespace CryptoExchange.Net.Authentication
|
||||
/// <param name="inputStream">The stream containing the json data</param>
|
||||
/// <param name="identifierKey">A key to identify the credentials for the API. For example, when set to `binanceKey` the json data should contain a value for the property `binanceKey`. Defaults to 'apiKey'.</param>
|
||||
/// <param name="identifierSecret">A key to identify the credentials for the API. For example, when set to `binanceSecret` the json data should contain a value for the property `binanceSecret`. Defaults to 'apiSecret'.</param>
|
||||
public ApiCredentials(Stream inputStream, string? identifierKey = null, string? identifierSecret = null)
|
||||
public static ApiCredentials FromStream(Stream inputStream, string? identifierKey = null, string? identifierSecret = null)
|
||||
{
|
||||
var accessor = new SystemTextJsonStreamMessageAccessor();
|
||||
if (!accessor.Read(inputStream, false).Result)
|
||||
@ -75,11 +66,9 @@ namespace CryptoExchange.Net.Authentication
|
||||
var secret = accessor.GetValue<string>(MessagePath.Get().Property(identifierSecret ?? "apiSecret"));
|
||||
if (key == null || secret == null)
|
||||
throw new ArgumentException("apiKey or apiSecret value not found in Json credential file");
|
||||
|
||||
Key = key;
|
||||
Secret = secret;
|
||||
|
||||
|
||||
inputStream.Seek(0, SeekOrigin.Begin);
|
||||
return new ApiCredentials(key, secret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ namespace CryptoExchange.Net.Authentication
|
||||
/// <summary>
|
||||
/// Get the API key of the current credentials
|
||||
/// </summary>
|
||||
public string ApiKey => _credentials.Key;
|
||||
public string ApiKey => _credentials.Key!;
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
@ -39,7 +39,7 @@ namespace CryptoExchange.Net.Authentication
|
||||
/// <param name="credentials"></param>
|
||||
protected AuthenticationProvider(ApiCredentials credentials)
|
||||
{
|
||||
if (credentials.Secret == null)
|
||||
if (credentials.Key == null || credentials.Secret == null)
|
||||
throw new ArgumentException("ApiKey/Secret needed");
|
||||
|
||||
_credentials = credentials;
|
||||
|
@ -109,6 +109,16 @@ namespace CryptoExchange.Net.Clients
|
||||
return apiClient;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Apply the options delegate to a new options instance
|
||||
/// </summary>
|
||||
protected static T ApplyOptionsDelegate<T>(Action<T>? del) where T: new()
|
||||
{
|
||||
var opts = new T();
|
||||
del?.Invoke(opts);
|
||||
return opts;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dispose
|
||||
/// </summary>
|
||||
|
@ -59,5 +59,6 @@
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.2" />
|
||||
<PackageReference Include="System.Text.Json" Version="8.0.5" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="8.0.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -8,30 +8,21 @@
|
||||
/// <summary>
|
||||
/// The host address of the proxy
|
||||
/// </summary>
|
||||
public string Host { get; }
|
||||
public string Host { get; set; }
|
||||
/// <summary>
|
||||
/// The port of the proxy
|
||||
/// </summary>
|
||||
public int Port { get; }
|
||||
public int Port { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The login of the proxy
|
||||
/// </summary>
|
||||
public string? Login { get; }
|
||||
public string? Login { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The password of the proxy
|
||||
/// </summary>
|
||||
public string? Password { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create new settings for a proxy
|
||||
/// </summary>
|
||||
/// <param name="host">The proxy hostname/ip</param>
|
||||
/// <param name="port">The proxy port</param>
|
||||
public ApiProxy(string host, int port): this(host, port, null, null)
|
||||
{
|
||||
}
|
||||
public string? Password { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Create new settings for a proxy
|
||||
@ -40,7 +31,7 @@
|
||||
/// <param name="port">The proxy port</param>
|
||||
/// <param name="login">The proxy login</param>
|
||||
/// <param name="password">The proxy password</param>
|
||||
public ApiProxy(string host, int port, string? login, string? password)
|
||||
public ApiProxy(string host, int port, string? login = null, string? password = null)
|
||||
{
|
||||
Host = host;
|
||||
Port = port;
|
||||
|
@ -19,19 +19,15 @@ namespace CryptoExchange.Net.Objects.Options
|
||||
public TimeSpan? TimestampRecalculationInterval { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a copy of this options
|
||||
/// Set the values of this options on the target options
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
public virtual T Copy<T>() where T : RestApiOptions, new()
|
||||
public T Set<T>(T item) where T : RestApiOptions, new()
|
||||
{
|
||||
return new T
|
||||
{
|
||||
ApiCredentials = ApiCredentials?.Copy(),
|
||||
OutputOriginalData = OutputOriginalData,
|
||||
AutoTimestamp = AutoTimestamp,
|
||||
TimestampRecalculationInterval = TimestampRecalculationInterval
|
||||
};
|
||||
item.ApiCredentials = ApiCredentials?.Copy();
|
||||
item.OutputOriginalData = OutputOriginalData;
|
||||
item.AutoTimestamp = AutoTimestamp;
|
||||
item.TimestampRecalculationInterval = TimestampRecalculationInterval;
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -29,25 +29,21 @@ namespace CryptoExchange.Net.Objects.Options
|
||||
public TimeSpan CachingMaxAge { get; set; } = TimeSpan.FromSeconds(5);
|
||||
|
||||
/// <summary>
|
||||
/// Create a copy of this options
|
||||
/// Set the values of this options on the target options
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
public T Copy<T>() where T : RestExchangeOptions, new()
|
||||
public T Set<T>(T item) where T : RestExchangeOptions, new()
|
||||
{
|
||||
return new T
|
||||
{
|
||||
OutputOriginalData = OutputOriginalData,
|
||||
AutoTimestamp = AutoTimestamp,
|
||||
TimestampRecalculationInterval = TimestampRecalculationInterval,
|
||||
ApiCredentials = ApiCredentials?.Copy(),
|
||||
Proxy = Proxy,
|
||||
RequestTimeout = RequestTimeout,
|
||||
RateLimiterEnabled = RateLimiterEnabled,
|
||||
RateLimitingBehaviour = RateLimitingBehaviour,
|
||||
CachingEnabled = CachingEnabled,
|
||||
CachingMaxAge = CachingMaxAge,
|
||||
};
|
||||
item.OutputOriginalData = OutputOriginalData;
|
||||
item.AutoTimestamp = AutoTimestamp;
|
||||
item.TimestampRecalculationInterval = TimestampRecalculationInterval;
|
||||
item.ApiCredentials = ApiCredentials?.Copy();
|
||||
item.Proxy = Proxy;
|
||||
item.RequestTimeout = RequestTimeout;
|
||||
item.RateLimiterEnabled = RateLimiterEnabled;
|
||||
item.RateLimitingBehaviour = RateLimitingBehaviour;
|
||||
item.CachingEnabled = CachingEnabled;
|
||||
item.CachingMaxAge = CachingMaxAge;
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,15 +62,13 @@ namespace CryptoExchange.Net.Objects.Options
|
||||
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||
|
||||
/// <summary>
|
||||
/// Create a copy of this options
|
||||
/// Set the values of this options on the target options
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
public new T Copy<T>() where T : RestExchangeOptions<TEnvironment>, new()
|
||||
public new T Set<T>(T target) where T : RestExchangeOptions<TEnvironment>, new()
|
||||
{
|
||||
var result = base.Copy<T>();
|
||||
result.Environment = Environment;
|
||||
return result;
|
||||
base.Set(target);
|
||||
target.Environment = Environment;
|
||||
return target;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,19 +20,15 @@ namespace CryptoExchange.Net.Objects.Options
|
||||
public int? MaxSocketConnections { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a copy of this options
|
||||
/// Set the values of this options on the target options
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
public T Copy<T>() where T : SocketApiOptions, new()
|
||||
public T Set<T>(T item) where T : SocketApiOptions, new()
|
||||
{
|
||||
return new T
|
||||
{
|
||||
ApiCredentials = ApiCredentials?.Copy(),
|
||||
OutputOriginalData = OutputOriginalData,
|
||||
SocketNoDataTimeout = SocketNoDataTimeout,
|
||||
MaxSocketConnections = MaxSocketConnections,
|
||||
};
|
||||
item.ApiCredentials = ApiCredentials?.Copy();
|
||||
item.OutputOriginalData = OutputOriginalData;
|
||||
item.SocketNoDataTimeout = SocketNoDataTimeout;
|
||||
item.MaxSocketConnections = MaxSocketConnections;
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -57,24 +57,22 @@ namespace CryptoExchange.Net.Objects.Options
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
public T Copy<T>() where T : SocketExchangeOptions, new()
|
||||
public T Set<T>(T item) where T : SocketExchangeOptions, new()
|
||||
{
|
||||
return new T
|
||||
{
|
||||
ApiCredentials = ApiCredentials?.Copy(),
|
||||
OutputOriginalData = OutputOriginalData,
|
||||
ReconnectPolicy = ReconnectPolicy,
|
||||
DelayAfterConnect = DelayAfterConnect,
|
||||
MaxConcurrentResubscriptionsPerSocket = MaxConcurrentResubscriptionsPerSocket,
|
||||
ReconnectInterval = ReconnectInterval,
|
||||
SocketNoDataTimeout = SocketNoDataTimeout,
|
||||
SocketSubscriptionsCombineTarget = SocketSubscriptionsCombineTarget,
|
||||
MaxSocketConnections = MaxSocketConnections,
|
||||
Proxy = Proxy,
|
||||
RequestTimeout = RequestTimeout,
|
||||
RateLimitingBehaviour = RateLimitingBehaviour,
|
||||
RateLimiterEnabled = RateLimiterEnabled,
|
||||
};
|
||||
item.ApiCredentials = ApiCredentials?.Copy();
|
||||
item.OutputOriginalData = OutputOriginalData;
|
||||
item.ReconnectPolicy = ReconnectPolicy;
|
||||
item.DelayAfterConnect = DelayAfterConnect;
|
||||
item.MaxConcurrentResubscriptionsPerSocket = MaxConcurrentResubscriptionsPerSocket;
|
||||
item.ReconnectInterval = ReconnectInterval;
|
||||
item.SocketNoDataTimeout = SocketNoDataTimeout;
|
||||
item.SocketSubscriptionsCombineTarget = SocketSubscriptionsCombineTarget;
|
||||
item.MaxSocketConnections = MaxSocketConnections;
|
||||
item.Proxy = Proxy;
|
||||
item.RequestTimeout = RequestTimeout;
|
||||
item.RateLimitingBehaviour = RateLimitingBehaviour;
|
||||
item.RateLimiterEnabled = RateLimiterEnabled;
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
||||
@ -93,15 +91,13 @@ namespace CryptoExchange.Net.Objects.Options
|
||||
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||
|
||||
/// <summary>
|
||||
/// Create a copy of this options
|
||||
/// Set the values of this options on the target options
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
public new T Copy<T>() where T : SocketExchangeOptions<TEnvironment>, new()
|
||||
public new T Set<T>(T target) where T : SocketExchangeOptions<TEnvironment>, new()
|
||||
{
|
||||
var result = base.Copy<T>();
|
||||
result.Environment = Environment;
|
||||
return result;
|
||||
base.Set(target);
|
||||
target.Environment = Environment;
|
||||
return target;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,14 +24,14 @@
|
||||
/// <summary>
|
||||
/// Name of the environment
|
||||
/// </summary>
|
||||
public string EnvironmentName { get; init; }
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
protected TradeEnvironment(string name)
|
||||
{
|
||||
EnvironmentName = name;
|
||||
Name = name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ namespace CryptoExchange.Net.Requests
|
||||
/// </summary>
|
||||
public class RequestFactory : IRequestFactory
|
||||
{
|
||||
private HttpClient? _httpClient;
|
||||
private HttpClient? _httpClient;
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Configure(ApiProxy? proxy, TimeSpan requestTimeout, HttpClient? client = null)
|
||||
|
26
Examples/example-config.json
Normal file
26
Examples/example-config.json
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"ExchangeApiOptions": {
|
||||
"ApiCredentials": {
|
||||
"Key": "APIKEY",
|
||||
"Secret": "SECRET"
|
||||
},
|
||||
"Environment": {
|
||||
"name": "live"
|
||||
},
|
||||
"Rest":{
|
||||
"RequestTimeout": "00:00:20",
|
||||
"CachingEnabled": true,
|
||||
"OutputOriginalData": true,
|
||||
"Proxy": {
|
||||
"Host": "https://127.0.0.1",
|
||||
"Port": 8080,
|
||||
"Login": "User",
|
||||
"Password": "Pass"
|
||||
}
|
||||
},
|
||||
"Socket":{
|
||||
"RequestTimeout": "00:00:05",
|
||||
"SocketSubscriptionsCombineTarget": 15
|
||||
}
|
||||
}
|
||||
}
|
255
docs/index.html
255
docs/index.html
@ -356,7 +356,7 @@
|
||||
<section id="idocs_di">
|
||||
<h2>Dependency Injection</h2>
|
||||
<p>
|
||||
All client libraries support and encourage usage via the Dotnet dependency injection system. Add all necesary services per exchange by calling the <code>Add[Library]();</code> extension method on the service collection, or use <code>AddCryptoClients()</code> to add all exchange services in a single class. <a href="#idocs_options_set">Options</a> for the clients can be passed as parameters.
|
||||
All client libraries support and encourage usage via the Dotnet dependency injection system. Add all necesary services per exchange by calling the <code>Add[Library]();</code> extension method on the service collection, or use <code>AddCryptoClients()</code> to add all exchange services in a single class. Options for the clients can be passed as parameters or read from the configuration. See <a href="#idocs_options_set">Options</a>.
|
||||
</p>
|
||||
<div class="alert alert-info">Using the dependecy injection mechanism also makes sure the HttpClient is used correctly</div>
|
||||
<div class="tab-wrap">
|
||||
@ -2334,7 +2334,7 @@ options.ApiCredentials = new ApiCredentials("YOUR PUBLIC KEY", "YOUR PRIVATE KEY
|
||||
<h2>Setting options</h2>
|
||||
|
||||
<b>Dependency injection</b>
|
||||
<p>When adding a library to the service collection (see <a href="#idocs_di">Dependency Injection</a>) the options for the clients can be provided as argument to the calls. Options are split between the REST and the websocket client.</p>
|
||||
<p>When adding a library to the service collection (see <a href="#idocs_di">Dependency Injection</a>) the options for the clients can be provided as argument to the calls or read from configuration.</p>
|
||||
<div class="tab-wrap">
|
||||
<ul class="nav nav-tabs" id="options" role="tablist" style="margin-bottom: -16px;">
|
||||
<li class="nav-item" role="presentation">
|
||||
@ -2404,153 +2404,206 @@ options.ApiCredentials = new ApiCredentials("YOUR PUBLIC KEY", "YOUR PRIVATE KEY
|
||||
</div>
|
||||
<div class="tab-pane fade" id="options-binance" role="tabpanel" aria-labelledby="options-binance-tab">
|
||||
<pre><code>builder.Services.AddBinance(
|
||||
restOptions => {
|
||||
restOptions.RequestTimeout = TimeSpan.FromSeconds(30);
|
||||
},
|
||||
socketOptions => {
|
||||
socketOptions.RequestTimeout = TimeSpan.FromSeconds(10);
|
||||
});</code></pre>
|
||||
options => {
|
||||
options.Rest.RequestTimeout = TimeSpan.FromSeconds(30);
|
||||
options.Socket.RequestTimeout = TimeSpan.FromSeconds(5);
|
||||
});
|
||||
|
||||
// OR
|
||||
|
||||
// see https://github.com/JKorf/CryptoExchange.Net/tree/master/Examples/example-config.json for an example configuration
|
||||
builder.Services.AddBinance(builder.Configuration.GetSection("Binance"));</code></pre>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="options-bingx" role="tabpanel" aria-labelledby="options-bingx-tab">
|
||||
<pre><code>builder.Services.AddBingX(
|
||||
restOptions => {
|
||||
restOptions.RequestTimeout = TimeSpan.FromSeconds(30);
|
||||
},
|
||||
socketOptions => {
|
||||
socketOptions.RequestTimeout = TimeSpan.FromSeconds(10);
|
||||
});</code></pre>
|
||||
options => {
|
||||
options.Rest.RequestTimeout = TimeSpan.FromSeconds(30);
|
||||
options.Socket.RequestTimeout = TimeSpan.FromSeconds(5);
|
||||
});
|
||||
|
||||
// OR
|
||||
|
||||
// see https://github.com/JKorf/CryptoExchange.Net/tree/master/Examples/example-config.json for an example configuration
|
||||
builder.Services.AddBingX(builder.Configuration.GetSection("BingX"));</code></pre></code></pre>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="options-bitfinex" role="tabpanel" aria-labelledby="options-bitfinex-tab">
|
||||
<pre><code>builder.Services.AddBitfinex(
|
||||
restOptions => {
|
||||
restOptions.RequestTimeout = TimeSpan.FromSeconds(30);
|
||||
},
|
||||
socketOptions => {
|
||||
socketOptions.RequestTimeout = TimeSpan.FromSeconds(10);
|
||||
});</code></pre>
|
||||
options => {
|
||||
options.Rest.RequestTimeout = TimeSpan.FromSeconds(30);
|
||||
options.Socket.RequestTimeout = TimeSpan.FromSeconds(5);
|
||||
});
|
||||
|
||||
// OR
|
||||
|
||||
// see https://github.com/JKorf/CryptoExchange.Net/tree/master/Examples/example-config.json for an example configuration
|
||||
builder.Services.AddBitfinex(builder.Configuration.GetSection("Bitfinex"));</code></pre>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="options-bitget" role="tabpanel" aria-labelledby="options-bitget-tab">
|
||||
<pre><code>builder.Services.AddBitget(
|
||||
restOptions => {
|
||||
restOptions.RequestTimeout = TimeSpan.FromSeconds(30);
|
||||
},
|
||||
socketOptions => {
|
||||
socketOptions.RequestTimeout = TimeSpan.FromSeconds(10);
|
||||
});</code></pre>
|
||||
options => {
|
||||
options.Rest.RequestTimeout = TimeSpan.FromSeconds(30);
|
||||
options.Socket.RequestTimeout = TimeSpan.FromSeconds(5);
|
||||
});
|
||||
|
||||
// OR
|
||||
|
||||
// see https://github.com/JKorf/CryptoExchange.Net/tree/master/Examples/example-config.json for an example configuration
|
||||
builder.Services.AddBitget(builder.Configuration.GetSection("Bitget"));</code></pre>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="options-bitmart" role="tabpanel" aria-labelledby="options-bitmart-tab">
|
||||
<pre><code>builder.Services.AddBitMart(
|
||||
restOptions => {
|
||||
restOptions.RequestTimeout = TimeSpan.FromSeconds(30);
|
||||
},
|
||||
socketOptions => {
|
||||
socketOptions.RequestTimeout = TimeSpan.FromSeconds(10);
|
||||
});</code></pre>
|
||||
options => {
|
||||
options.Rest.RequestTimeout = TimeSpan.FromSeconds(30);
|
||||
options.Socket.RequestTimeout = TimeSpan.FromSeconds(5);
|
||||
});
|
||||
|
||||
// OR
|
||||
|
||||
// see https://github.com/JKorf/CryptoExchange.Net/tree/master/Examples/example-config.json for an example configuration
|
||||
builder.Services.AddBitMart(builder.Configuration.GetSection("BitMart"));</code></pre>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="options-bybit" role="tabpanel" aria-labelledby="options-bybit-tab">
|
||||
<pre><code>builder.Services.AddBybit(
|
||||
restOptions => {
|
||||
restOptions.RequestTimeout = TimeSpan.FromSeconds(30);
|
||||
},
|
||||
socketOptions => {
|
||||
socketOptions.RequestTimeout = TimeSpan.FromSeconds(10);
|
||||
});</code></pre>
|
||||
options => {
|
||||
options.Rest.RequestTimeout = TimeSpan.FromSeconds(30);
|
||||
options.Socket.RequestTimeout = TimeSpan.FromSeconds(5);
|
||||
});
|
||||
|
||||
// OR
|
||||
|
||||
// see https://github.com/JKorf/CryptoExchange.Net/tree/master/Examples/example-config.json for an example configuration
|
||||
builder.Services.AddBybit(builder.Configuration.GetSection("Bybit"));</code></pre>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="options-coinbase" role="tabpanel" aria-labelledby="options-coinbase-tab">
|
||||
<pre><code>builder.Services.AddCoinbase(
|
||||
restOptions => {
|
||||
restOptions.RequestTimeout = TimeSpan.FromSeconds(30);
|
||||
},
|
||||
socketOptions => {
|
||||
socketOptions.RequestTimeout = TimeSpan.FromSeconds(10);
|
||||
});</code></pre>
|
||||
options => {
|
||||
options.Rest.RequestTimeout = TimeSpan.FromSeconds(30);
|
||||
options.Socket.RequestTimeout = TimeSpan.FromSeconds(5);
|
||||
});
|
||||
|
||||
// OR
|
||||
|
||||
// see https://github.com/JKorf/CryptoExchange.Net/tree/master/Examples/example-config.json for an example configuration
|
||||
builder.Services.AddCoinbase(builder.Configuration.GetSection("Coinbase"));</code></pre>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="options-coingecko" role="tabpanel" aria-labelledby="options-coingecko-tab">
|
||||
<pre><code>builder.Services.AddCoinGecko(
|
||||
restOptions => {
|
||||
restOptions.RequestTimeout = TimeSpan.FromSeconds(30);
|
||||
});</code></pre>
|
||||
options => {
|
||||
options.RequestTimeout = TimeSpan.FromSeconds(30);
|
||||
});
|
||||
|
||||
// OR
|
||||
|
||||
// see https://github.com/JKorf/CryptoExchange.Net/tree/master/Examples/example-config.json for an example configuration
|
||||
builder.Services.AddCoinGecko(builder.Configuration.GetSection("CoinGecko"));</code></pre>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="options-coinex" role="tabpanel" aria-labelledby="options-coinex-tab">
|
||||
<pre><code>builder.Services.AddCoinEx(
|
||||
restOptions => {
|
||||
restOptions.RequestTimeout = TimeSpan.FromSeconds(30);
|
||||
},
|
||||
socketOptions => {
|
||||
socketOptions.RequestTimeout = TimeSpan.FromSeconds(10);
|
||||
});</code></pre>
|
||||
options => {
|
||||
options.Rest.RequestTimeout = TimeSpan.FromSeconds(30);
|
||||
options.Socket.RequestTimeout = TimeSpan.FromSeconds(5);
|
||||
});
|
||||
|
||||
// OR
|
||||
|
||||
// see https://github.com/JKorf/CryptoExchange.Net/tree/master/Examples/example-config.json for an example configuration
|
||||
builder.Services.AddCoinEx(builder.Configuration.GetSection("CoinEx"));</code></pre>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="options-cryptocom" role="tabpanel" aria-labelledby="options-cryptocom-tab">
|
||||
<pre><code>builder.Services.AddCryptoCom(
|
||||
restOptions => {
|
||||
restOptions.RequestTimeout = TimeSpan.FromSeconds(30);
|
||||
},
|
||||
socketOptions => {
|
||||
socketOptions.RequestTimeout = TimeSpan.FromSeconds(10);
|
||||
});</code></pre>
|
||||
options => {
|
||||
options.Rest.RequestTimeout = TimeSpan.FromSeconds(30);
|
||||
options.Socket.RequestTimeout = TimeSpan.FromSeconds(5);
|
||||
});
|
||||
|
||||
// OR
|
||||
|
||||
// see https://github.com/JKorf/CryptoExchange.Net/tree/master/Examples/example-config.json for an example configuration
|
||||
builder.Services.AddCryptoCom(builder.Configuration.GetSection("CryptoCom"));</code></pre>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="options-gateio" role="tabpanel" aria-labelledby="options-gateio-tab">
|
||||
<pre><code>builder.Services.AddGateIo(
|
||||
restOptions => {
|
||||
restOptions.RequestTimeout = TimeSpan.FromSeconds(30);
|
||||
},
|
||||
socketOptions => {
|
||||
socketOptions.RequestTimeout = TimeSpan.FromSeconds(10);
|
||||
});</code></pre>
|
||||
options => {
|
||||
options.Rest.RequestTimeout = TimeSpan.FromSeconds(30);
|
||||
options.Socket.RequestTimeout = TimeSpan.FromSeconds(5);
|
||||
});
|
||||
|
||||
// OR
|
||||
|
||||
// see https://github.com/JKorf/CryptoExchange.Net/tree/master/Examples/example-config.json for an example configuration
|
||||
builder.Services.AddGateIo(builder.Configuration.GetSection("GateIo"));</code></pre>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="options-htx" role="tabpanel" aria-labelledby="options-htx-tab">
|
||||
<pre><code>builder.Services.AddHTX(
|
||||
restOptions => {
|
||||
restOptions.RequestTimeout = TimeSpan.FromSeconds(30);
|
||||
},
|
||||
socketOptions => {
|
||||
socketOptions.RequestTimeout = TimeSpan.FromSeconds(10);
|
||||
});</code></pre>
|
||||
options => {
|
||||
options.Rest.RequestTimeout = TimeSpan.FromSeconds(30);
|
||||
options.Socket.RequestTimeout = TimeSpan.FromSeconds(5);
|
||||
});
|
||||
|
||||
// OR
|
||||
|
||||
// see https://github.com/JKorf/CryptoExchange.Net/tree/master/Examples/example-config.json for an example configuration
|
||||
builder.Services.AddHTX(builder.Configuration.GetSection("HTX"));</code></pre>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="options-kraken" role="tabpanel" aria-labelledby="options-kraken-tab">
|
||||
<pre><code>builder.Services.AddKraken(
|
||||
restOptions => {
|
||||
restOptions.RequestTimeout = TimeSpan.FromSeconds(30);
|
||||
},
|
||||
socketOptions => {
|
||||
socketOptions.RequestTimeout = TimeSpan.FromSeconds(10);
|
||||
});</code></pre>
|
||||
options => {
|
||||
options.Rest.RequestTimeout = TimeSpan.FromSeconds(30);
|
||||
options.Socket.RequestTimeout = TimeSpan.FromSeconds(5);
|
||||
});
|
||||
|
||||
// OR
|
||||
|
||||
// see https://github.com/JKorf/CryptoExchange.Net/tree/master/Examples/example-config.json for an example configuration
|
||||
builder.Services.AddKraken(builder.Configuration.GetSection("Kraken"));</code></pre>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="options-kucoin" role="tabpanel" aria-labelledby="options-kucoin-tab">
|
||||
<pre><code>builder.Services.AddKucoin(
|
||||
restOptions => {
|
||||
restOptions.RequestTimeout = TimeSpan.FromSeconds(30);
|
||||
},
|
||||
socketOptions => {
|
||||
socketOptions.RequestTimeout = TimeSpan.FromSeconds(10);
|
||||
});</code></pre>
|
||||
options => {
|
||||
options.Rest.RequestTimeout = TimeSpan.FromSeconds(30);
|
||||
options.Socket.RequestTimeout = TimeSpan.FromSeconds(5);
|
||||
});
|
||||
|
||||
// OR
|
||||
|
||||
// see https://github.com/JKorf/CryptoExchange.Net/tree/master/Examples/example-config.json for an example configuration
|
||||
builder.Services.AddKucoin(builder.Configuration.GetSection("Kucoin"));</code></pre>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="options-mexc" role="tabpanel" aria-labelledby="options-mexc-tab">
|
||||
<pre><code>builder.Services.AddMexc(
|
||||
restOptions => {
|
||||
restOptions.RequestTimeout = TimeSpan.FromSeconds(30);
|
||||
},
|
||||
socketOptions => {
|
||||
socketOptions.RequestTimeout = TimeSpan.FromSeconds(10);
|
||||
});</code></pre>
|
||||
options => {
|
||||
options.Rest.RequestTimeout = TimeSpan.FromSeconds(30);
|
||||
options.Socket.RequestTimeout = TimeSpan.FromSeconds(5);
|
||||
});
|
||||
|
||||
// OR
|
||||
|
||||
// see https://github.com/JKorf/CryptoExchange.Net/tree/master/Examples/example-config.json for an example configuration
|
||||
builder.Services.AddMexc(builder.Configuration.GetSection("Mexc"));</code></pre>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="options-okx" role="tabpanel" aria-labelledby="options-okx-tab">
|
||||
<pre><code>builder.Services.AddOKX(
|
||||
restOptions => {
|
||||
restOptions.RequestTimeout = TimeSpan.FromSeconds(30);
|
||||
},
|
||||
socketOptions => {
|
||||
socketOptions.RequestTimeout = TimeSpan.FromSeconds(10);
|
||||
});</code></pre>
|
||||
options => {
|
||||
options.Rest.RequestTimeout = TimeSpan.FromSeconds(30);
|
||||
options.Socket.RequestTimeout = TimeSpan.FromSeconds(5);
|
||||
});
|
||||
|
||||
// OR
|
||||
|
||||
// see https://github.com/JKorf/CryptoExchange.Net/tree/master/Examples/example-config.json for an example configuration
|
||||
builder.Services.AddOKX(builder.Configuration.GetSection("OKX"));</code></pre>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="options-whitebit" role="tabpanel" aria-labelledby="options-whitebit-tab">
|
||||
<pre><code>builder.Services.AddWhiteBit(
|
||||
restOptions => {
|
||||
restOptions.RequestTimeout = TimeSpan.FromSeconds(30);
|
||||
},
|
||||
socketOptions => {
|
||||
socketOptions.RequestTimeout = TimeSpan.FromSeconds(10);
|
||||
});</code></pre>
|
||||
options => {
|
||||
options.Rest.RequestTimeout = TimeSpan.FromSeconds(30);
|
||||
options.Socket.RequestTimeout = TimeSpan.FromSeconds(5);
|
||||
});
|
||||
|
||||
// OR
|
||||
|
||||
// see https://github.com/JKorf/CryptoExchange.Net/tree/master/Examples/example-config.json for an example configuration
|
||||
builder.Services.AddWhiteBit(builder.Configuration.GetSection("WhiteBit"));</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
Loading…
x
Reference in New Issue
Block a user