mirror of
https://github.com/JKorf/CryptoExchange.Net.git
synced 2026-08-12 17:03:10 +00:00
2f9f97f4e8
Updated API credential logic, exchange implementation are expected to provide their own credentials implementation with ApiCredentials as base class Removed ApiCredentials implementation used by most exchanges Removed ApiCredentialsType Enum Added CredentialSet base class and implementations for defining different API credentials Added optional type param to AuthenticationProvider for the specific API credential type to improve type safety Moved AuthenticationProvider/ApiCredentials from BaseApiClient to RestApiClient/SocketApiClient base classes Added optional type params to RestApiClient/SocketApiClient base class to specify the AuthenticationProvider type and credentials type to improve type safety Moved SetOptions/SetApiCredentials from BaseApiClient to RestApiClient/SocketApiClient Extracted LibraryOptions<TRestOptions, TSocketOptions, TEnvironment> without TApiCredentials for libraries without API credentials Removed ApiCredentials from ApiOptions, credentials can only be configured at library, rest or socket level Added EnvironmentName to RestApiClient/SocketApiClient property Added Unknown enum value to Shared interfaces SharedOrderStatus, SharedTransferStatus and SharedTriggerOrderStatus enums Updated Enum converter to map value to an undefined Enum value instead of the first Enum value Added support for checking for missing fields on RestIntegrationTest Added BytesToHexString and HexToBytesString to ExchangeHelpers static class Fixed bug where WebSocket connections are not reconnected when configuring Proxy with SetUpdates Removed legacy CryptoBaseClient, CryptoRestClient and CryptoSocketClient
166 lines
6.3 KiB
C#
166 lines
6.3 KiB
C#
using CryptoExchange.Net.Authentication;
|
|
using CryptoExchange.Net.Objects;
|
|
using CryptoExchange.Net.Objects.Options;
|
|
using Microsoft.Extensions.Logging;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Net;
|
|
using System.Net.Http;
|
|
|
|
namespace CryptoExchange.Net
|
|
{
|
|
/// <summary>
|
|
/// Helpers for client libraries
|
|
/// </summary>
|
|
public static class LibraryHelpers
|
|
{
|
|
private static ILogger? _staticLogger;
|
|
/// <summary>
|
|
/// Static logger
|
|
/// </summary>
|
|
public static ILogger? StaticLogger
|
|
{
|
|
get => _staticLogger;
|
|
internal set
|
|
{
|
|
if (_staticLogger != null)
|
|
return;
|
|
|
|
_staticLogger = value;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Client order id separator
|
|
/// </summary>
|
|
public const string ClientOrderIdSeparator = "JK";
|
|
|
|
private static Dictionary<string, string> _defaultClientReferences = new Dictionary<string, string>()
|
|
{
|
|
{ "Binance.Spot", "x-VICEW9VV" },
|
|
{ "Binance.Futures", "x-d63tKbx3" },
|
|
{ "BingX", "easytrading" },
|
|
{ "Bitfinex", "kCCe-CNBO" },
|
|
{ "Bitget", "6x21p" },
|
|
{ "BitMart", "EASYTRADING0001" },
|
|
{ "BitMEX", "Sent from JKorf" },
|
|
{ "BloFin", "5c07cf695885c282" },
|
|
{ "Bybit", "Zx000356" },
|
|
{ "CoinEx", "x-147866029-" },
|
|
{ "GateIo", "copytraderpw" },
|
|
{ "HTX", "AA1ef14811" },
|
|
{ "Kucoin.FuturesName", "Easytradingfutures" },
|
|
{ "Kucoin.FuturesKey", "9e08c05f-454d-4580-82af-2f4c7027fd00" },
|
|
{ "Kucoin.SpotName", "Easytrading" },
|
|
{ "Kucoin.SpotKey", "f8ae62cb-2b3d-420c-8c98-e1c17dd4e30a" },
|
|
{ "Mexc", "EASYT" },
|
|
{ "OKX", "1425d83a94fbBCDE" },
|
|
{ "XT", "4XWeqN10M1fcoI5L" },
|
|
};
|
|
|
|
/// <summary>
|
|
/// Apply broker id to a client order id
|
|
/// </summary>
|
|
/// <param name="clientOrderId"></param>
|
|
/// <param name="brokerId"></param>
|
|
/// <param name="maxLength"></param>
|
|
/// <param name="allowValueAdjustment"></param>
|
|
/// <returns></returns>
|
|
public static string ApplyBrokerId(string? clientOrderId, string brokerId, int maxLength, bool allowValueAdjustment)
|
|
{
|
|
var reservedLength = brokerId.Length + ClientOrderIdSeparator.Length;
|
|
|
|
if (clientOrderId?.Length + reservedLength > maxLength)
|
|
return clientOrderId!;
|
|
|
|
if (!string.IsNullOrEmpty(clientOrderId))
|
|
{
|
|
if (allowValueAdjustment)
|
|
clientOrderId = brokerId + ClientOrderIdSeparator + clientOrderId;
|
|
|
|
return clientOrderId!;
|
|
}
|
|
else
|
|
{
|
|
clientOrderId = ExchangeHelpers.AppendRandomString(brokerId + ClientOrderIdSeparator, maxLength);
|
|
}
|
|
|
|
return clientOrderId;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the client reference for an exchange if available
|
|
/// </summary>
|
|
public static string GetClientReference(Func<string?> optionsReference, string exchange, string? topic = null)
|
|
{
|
|
var optionsValue = optionsReference();
|
|
if (!string.IsNullOrEmpty(optionsValue))
|
|
return optionsValue!;
|
|
|
|
var key = exchange;
|
|
if (topic != null)
|
|
key += "." + topic;
|
|
|
|
return _defaultClientReferences.TryGetValue(key, out var id) ? id : throw new KeyNotFoundException($"{exchange} not found in configuration");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Create a new HttpMessageHandler instance
|
|
/// </summary>
|
|
public static HttpMessageHandler CreateHttpClientMessageHandler(RestExchangeOptions options)
|
|
{
|
|
#if NET5_0_OR_GREATER
|
|
var socketHandler = new SocketsHttpHandler();
|
|
try
|
|
{
|
|
if (options.HttpKeepAliveInterval != null && options.HttpKeepAliveInterval != TimeSpan.Zero)
|
|
{
|
|
socketHandler.KeepAlivePingPolicy = HttpKeepAlivePingPolicy.Always;
|
|
socketHandler.KeepAlivePingDelay = options.HttpKeepAliveInterval.Value;
|
|
socketHandler.KeepAlivePingTimeout = TimeSpan.FromSeconds(10);
|
|
}
|
|
|
|
socketHandler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
|
|
socketHandler.DefaultProxyCredentials = CredentialCache.DefaultCredentials;
|
|
|
|
socketHandler.EnableMultipleHttp2Connections = options.HttpEnableMultipleHttp2Connections;
|
|
socketHandler.PooledConnectionLifetime = options.HttpPooledConnectionLifetime;
|
|
socketHandler.PooledConnectionIdleTimeout = options.HttpPooledConnectionIdleTimeout;
|
|
socketHandler.MaxConnectionsPerServer = options.HttpMaxConnectionsPerServer;
|
|
}
|
|
catch (PlatformNotSupportedException) { }
|
|
catch (NotImplementedException) { } // Mono runtime throws NotImplementedException
|
|
|
|
if (options.Proxy != null)
|
|
{
|
|
socketHandler.Proxy = new WebProxy
|
|
{
|
|
Address = new Uri($"{options.Proxy.Host}:{options.Proxy.Port}"),
|
|
Credentials = options.Proxy.Password == null ? null : new NetworkCredential(options.Proxy.Login, options.Proxy.Password)
|
|
};
|
|
}
|
|
return socketHandler;
|
|
#else
|
|
var httpHandler = new HttpClientHandler();
|
|
try
|
|
{
|
|
httpHandler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
|
|
httpHandler.DefaultProxyCredentials = CredentialCache.DefaultCredentials;
|
|
}
|
|
catch (PlatformNotSupportedException) { }
|
|
catch (NotImplementedException) { } // Mono runtime throws NotImplementedException
|
|
|
|
if (options.Proxy != null)
|
|
{
|
|
httpHandler.Proxy = new WebProxy
|
|
{
|
|
Address = new Uri($"{options.Proxy.Host}:{options.Proxy.Port}"),
|
|
Credentials = options.Proxy.Password == null ? null : new NetworkCredential(options.Proxy.Login, options.Proxy.Password)
|
|
};
|
|
}
|
|
return httpHandler;
|
|
#endif
|
|
}
|
|
}
|
|
}
|