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
{
///
/// Helpers for client libraries
///
public static class LibraryHelpers
{
private static ILogger? _staticLogger;
///
/// Static logger
///
public static ILogger? StaticLogger
{
get => _staticLogger;
internal set
{
if (_staticLogger != null)
return;
_staticLogger = value;
}
}
///
/// Client order id separator
///
public const string ClientOrderIdSeparator = "JK";
private static Dictionary _defaultClientReferences = new Dictionary()
{
{ "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" },
{ "Weex", "b-WEEX111124-" },
{ "XT", "4XWeqN10M1fcoI5L" },
};
///
/// Apply broker id to a client order id
///
///
///
///
///
///
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;
}
///
/// Get the client reference for an exchange if available
///
public static string GetClientReference(Func 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");
}
///
/// Create a new HttpMessageHandler instance
///
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
}
}
}