mirror of
https://github.com/JKorf/CryptoExchange.Net.git
synced 2026-08-12 00:43:03 +00:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4a5832cccd | |||
| 4e47c4cbdf | |||
| 2af1520ecc | |||
| cf397af3ab | |||
| a1479705e2 |
@@ -443,6 +443,16 @@ namespace CryptoExchange.Net.Authentication
|
||||
return DateTimeConverter.ConvertToMilliseconds(GetTimestamp(apiClient)).Value.ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get millisecond timestamp as a long including the time sync offset from the api client
|
||||
/// </summary>
|
||||
/// <param name="apiClient"></param>
|
||||
/// <returns></returns>
|
||||
protected long GetMillisecondTimestampLong(RestApiClient apiClient)
|
||||
{
|
||||
return DateTimeConverter.ConvertToMilliseconds(GetTimestamp(apiClient)).Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the serialized request body
|
||||
/// </summary>
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
<PackageId>CryptoExchange.Net</PackageId>
|
||||
<Authors>JKorf</Authors>
|
||||
<Description>CryptoExchange.Net is a base library which is used to implement different cryptocurrency (exchange) API's. It provides a standardized way of implementing different API's, which results in a very similar experience for users of the API implementations.</Description>
|
||||
<PackageVersion>8.6.1</PackageVersion>
|
||||
<AssemblyVersion>8.6.1</AssemblyVersion>
|
||||
<FileVersion>8.6.1</FileVersion>
|
||||
<PackageVersion>8.7.0</PackageVersion>
|
||||
<AssemblyVersion>8.7.0</AssemblyVersion>
|
||||
<FileVersion>8.7.0</FileVersion>
|
||||
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
|
||||
<PackageTags>OKX;OKX.Net;Mexc;Mexc.Net;Kucoin;Kucoin.Net;Kraken;Kraken.Net;Huobi;Huobi.Net;CoinEx;CoinEx.Net;Bybit;Bybit.Net;Bitget;Bitget.Net;Bitfinex;Bitfinex.Net;Binance;Binance.Net;CryptoCurrency;CryptoCurrency Exchange</PackageTags>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
|
||||
@@ -261,6 +261,7 @@ namespace CryptoExchange.Net
|
||||
if (price != null)
|
||||
{
|
||||
adjustedPrice = AdjustValueStep(0, decimal.MaxValue, symbol.PriceStep, RoundingType.Down, price.Value);
|
||||
adjustedPrice = symbol.PriceSignificantFigures.HasValue ? RoundToSignificantDigits(adjustedPrice.Value, symbol.PriceSignificantFigures.Value, RoundingType.Closest) : adjustedPrice;
|
||||
adjustedPrice = symbol.PriceDecimals.HasValue ? RoundDown(price.Value, symbol.PriceDecimals.Value) : adjustedPrice;
|
||||
if (adjustedPrice != 0 && adjustedPrice * quantity < symbol.MinNotionalValue)
|
||||
{
|
||||
|
||||
@@ -183,7 +183,7 @@ namespace CryptoExchange.Net.Logging.Extensions
|
||||
_sendingData = LoggerMessage.Define<int, int, string>(
|
||||
LogLevel.Trace,
|
||||
new EventId(2028, "SendingData"),
|
||||
"[Sckt {SocketId}] [Req {RequestId}] sending messsage: {Data}");
|
||||
"[Sckt {SocketId}] [Req {RequestId}] sending message: {Data}");
|
||||
|
||||
_receivedMessageNotMatchedToAnyListener = LoggerMessage.Define<int, string, string>(
|
||||
LogLevel.Warning,
|
||||
|
||||
@@ -46,6 +46,10 @@
|
||||
/// </summary>
|
||||
public int? PriceDecimals { get; set; }
|
||||
/// <summary>
|
||||
/// The max amount of significant figures to use for price. For example with value of 5 these values are valid: 0.00001, 0.12300, 123.53, 12345, but this is not: 12345.1
|
||||
/// </summary>
|
||||
public int? PriceSignificantFigures { get; set; }
|
||||
/// <summary>
|
||||
/// Whether the symbol is currently available for trading
|
||||
/// </summary>
|
||||
public bool Trading { get; set; }
|
||||
|
||||
@@ -150,9 +150,9 @@ namespace CryptoExchange.Net.Testing
|
||||
/// </summary>
|
||||
/// <typeparam name="TClient"></typeparam>
|
||||
/// <exception cref="Exception"></exception>
|
||||
public static void CheckForMissingRestInterfaces<TClient>()
|
||||
public static void CheckForMissingRestInterfaces<TClient>(string[]? excludeInterfaces = null)
|
||||
{
|
||||
CheckForMissingInterfaces(typeof(TClient), typeof(Task));
|
||||
CheckForMissingInterfaces(typeof(TClient), typeof(Task), excludeInterfaces);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -160,26 +160,32 @@ namespace CryptoExchange.Net.Testing
|
||||
/// </summary>
|
||||
/// <typeparam name="TClient"></typeparam>
|
||||
/// <exception cref="Exception"></exception>
|
||||
public static void CheckForMissingSocketInterfaces<TClient>()
|
||||
public static void CheckForMissingSocketInterfaces<TClient>(string[]? excludeInterfaces = null)
|
||||
{
|
||||
CheckForMissingInterfaces(typeof(TClient), typeof(Task<CallResult<UpdateSubscription>>));
|
||||
CheckForMissingInterfaces(typeof(TClient), typeof(Task<CallResult<UpdateSubscription>>), excludeInterfaces);
|
||||
}
|
||||
|
||||
private static void CheckForMissingInterfaces(Type clientType, Type implementationTypes)
|
||||
private static void CheckForMissingInterfaces(Type clientType, Type implementationTypes, string[]? excludeInterfaces = null)
|
||||
{
|
||||
var assembly = Assembly.GetAssembly(clientType);
|
||||
var interfaceType = clientType.GetInterface("I" + clientType.Name);
|
||||
var clientInterfaces = assembly!.GetTypes().Where(t => t.Name.StartsWith("I" + clientType.Name) && !t.Name.EndsWith("Shared"));
|
||||
var clientInterfaces = assembly!.GetTypes()
|
||||
.Where(t => t.Name.StartsWith("I" + clientType.Name)
|
||||
&& !t.Name.EndsWith("Shared")
|
||||
&& (excludeInterfaces?.Contains(t.Name) != true));
|
||||
|
||||
foreach (var clientInterface in clientInterfaces)
|
||||
{
|
||||
var implementations = assembly.GetTypes().Where(t => clientInterface.IsAssignableFrom(t) && t != clientInterface);
|
||||
var implementations = assembly.GetTypes().Where(t => clientInterface.IsAssignableFrom(t) && !t.IsInterface && t != clientInterface);
|
||||
foreach (var implementation in implementations)
|
||||
{
|
||||
int methods = 0;
|
||||
foreach (var method in implementation.GetMethods().Where(m => implementationTypes.IsAssignableFrom(m.ReturnType)))
|
||||
{
|
||||
var interfaceMethod = clientInterface.GetMethod(method.Name, method.GetParameters().Select(p => p.ParameterType).ToArray()) ?? throw new Exception($"Missing interface for method {method.Name} in {implementation.Name} implementing interface {clientInterface.Name}");
|
||||
var interfaceMethod =
|
||||
clientInterface.GetMethod(method.Name, method.GetParameters().Select(p => p.ParameterType).ToArray())
|
||||
?? clientInterface.GetInterfaces().Select(x => x.GetMethod(method.Name, method.GetParameters().Select(p => p.ParameterType).ToArray())).FirstOrDefault()
|
||||
?? throw new Exception($"Missing interface for method {method.Name} in {implementation.Name} implementing interface {clientInterface.Name}");
|
||||
methods++;
|
||||
}
|
||||
|
||||
|
||||
@@ -66,6 +66,10 @@ Make a one time donation in a crypto currency of your choice. If you prefer to d
|
||||
Alternatively, sponsor me on Github using [Github Sponsors](https://github.com/sponsors/JKorf).
|
||||
|
||||
## Release notes
|
||||
* Version 8.7.0 - 21 Jan 2025
|
||||
* Added GetMillisecondTimestampLong helper method to AuthenticationProvider
|
||||
* Added PriceSignificationFigures to SharedSpotSymbol model
|
||||
|
||||
* Version 8.6.1 - 09 Jan 2025
|
||||
* Fixed websocket connection getting stuck after a ping frame timeout
|
||||
* Removed websocket Error callback when exception is expected
|
||||
|
||||
Reference in New Issue
Block a user