1
0
mirror of https://github.com/JKorf/CryptoExchange.Net.git synced 2026-08-12 00:43:03 +00:00

Compare commits

...

9 Commits

Author SHA1 Message Date
JKorf a16b19019f Updated version 2023-09-18 20:13:00 +02:00
JKorf 2443f576ac Fix for concurrency exception 2023-09-18 20:02:01 +02:00
JKorf 4fd7e44015 Logging 2023-09-16 18:26:10 +02:00
JKorf a0a3bda1c5 Updated version 2023-09-11 20:59:44 +02:00
JKorf 6bda7a3c73 Fixed nullreference if no Retry-After is returned after with a ratelimit error 2023-09-11 20:57:46 +02:00
JKorf 69a7a714cd Updated rate limiters to support multiple instances 2023-09-11 20:16:50 +02:00
JKorf 48e2e6468e Updated version 2023-09-04 18:10:18 +02:00
JKorf 4017ac780f ArrayConverter update for handling exponent notation, EnumConverter fix for writing enum values 2023-09-04 18:09:01 +02:00
JKorf a55cd1bb13 Docs 2023-08-26 20:04:38 +02:00
9 changed files with 60 additions and 30 deletions
+1 -1
View File
@@ -558,7 +558,7 @@ namespace CryptoExchange.Net
{
// Handle retry after header
var retryAfterHeader = responseHeaders.SingleOrDefault(r => r.Key.Equals("Retry-After", StringComparison.InvariantCultureIgnoreCase));
if (!retryAfterHeader.Value.Any())
if (retryAfterHeader.Value?.Any() != true)
return new ServerRateLimitError(data);
var value = retryAfterHeader.Value.First();
@@ -109,13 +109,21 @@ namespace CryptoExchange.Net.Converters
{
if (token.Type == JTokenType.Null)
value = null;
if (token.Type == JTokenType.Float)
value = token.Value<decimal>();
}
if ((property.PropertyType == typeof(decimal)
if (value is decimal)
{
property.SetValue(result, value);
}
else if ((property.PropertyType == typeof(decimal)
|| property.PropertyType == typeof(decimal?))
&& (value != null && value.ToString().IndexOf("e", StringComparison.OrdinalIgnoreCase) >= 0))
{
if (decimal.TryParse(value.ToString(), NumberStyles.Float, CultureInfo.InvariantCulture, out var dec))
var v = value.ToString();
if (decimal.TryParse(v, NumberStyles.Float, CultureInfo.InvariantCulture, out var dec))
property.SetValue(result, dec);
}
else
+15 -5
View File
@@ -117,22 +117,32 @@ namespace CryptoExchange.Net.Converters
/// <param name="enumValue"></param>
/// <returns></returns>
[return: NotNullIfNotNull("enumValue")]
public static string? GetString<T>(T enumValue)
public static string? GetString<T>(T enumValue) => GetString(typeof(T), enumValue);
[return: NotNullIfNotNull("enumValue")]
private static string? GetString(Type objectType, object? enumValue)
{
var objectType = typeof(T);
objectType = Nullable.GetUnderlyingType(objectType) ?? objectType;
if (!_mapping.TryGetValue(objectType, out var mapping))
mapping = AddMapping(objectType);
return enumValue == null ? null : (mapping.FirstOrDefault(v => v.Key.Equals(enumValue)).Value ?? enumValue.ToString());
return enumValue == null ? null : (mapping.FirstOrDefault(v => v.Key.Equals(enumValue)).Value ?? enumValue.ToString());
}
/// <inheritdoc />
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
{
var stringValue = GetString(value);
writer.WriteValue(stringValue);
if (value == null)
{
writer.WriteNull();
}
else
{
var stringValue = GetString(value.GetType(), value);
writer.WriteValue(stringValue);
}
}
}
}
+4 -4
View File
@@ -6,16 +6,16 @@
<PackageId>CryptoExchange.Net</PackageId>
<Authors>JKorf</Authors>
<Description>A base package for implementing cryptocurrency API's</Description>
<PackageVersion>6.1.0</PackageVersion>
<AssemblyVersion>6.1.0</AssemblyVersion>
<FileVersion>6.1.0</FileVersion>
<PackageVersion>6.1.3</PackageVersion>
<AssemblyVersion>6.1.3</AssemblyVersion>
<FileVersion>6.1.3</FileVersion>
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
<RepositoryType>git</RepositoryType>
<RepositoryUrl>https://github.com/JKorf/CryptoExchange.Net.git</RepositoryUrl>
<PackageProjectUrl>https://github.com/JKorf/CryptoExchange.Net</PackageProjectUrl>
<NeutralLanguage>en</NeutralLanguage>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageReleaseNotes>6.1.0 - Added support for ratelimiting on socket connections, Added rest ratelimit handling and parsing, Added ServerRatelimitError error</PackageReleaseNotes>
<PackageReleaseNotes>6.1.3 - Fix for concurrency exception in socket subscription</PackageReleaseNotes>
<Nullable>enable</Nullable>
<LangVersion>10.0</LangVersion>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
+11 -11
View File
@@ -117,10 +117,10 @@ namespace CryptoExchange.Net.Objects
{
int totalWaitTime = 0;
EndpointRateLimiter? endpointLimit;
List<EndpointRateLimiter> endpointLimits;
lock (_limiterLock)
endpointLimit = _limiters.OfType<EndpointRateLimiter>().SingleOrDefault(h => h.Endpoints.Contains(endpoint) && (h.Method == null || h.Method == method));
if(endpointLimit != null)
endpointLimits = _limiters.OfType<EndpointRateLimiter>().Where(h => h.Endpoints.Contains(endpoint) && (h.Method == null || h.Method == method)).ToList();
foreach (var endpointLimit in endpointLimits)
{
var waitResult = await ProcessTopic(logger, endpointLimit, endpoint, requestWeight, limitBehaviour, ct).ConfigureAwait(false);
if (!waitResult)
@@ -129,7 +129,7 @@ namespace CryptoExchange.Net.Objects
totalWaitTime += waitResult.Data;
}
if (endpointLimit?.IgnoreOtherRateLimits == true)
if (endpointLimits.Any(l => l.IgnoreOtherRateLimits))
return new CallResult<int>(totalWaitTime);
List<PartialEndpointRateLimiter> partialEndpointLimits;
@@ -169,10 +169,10 @@ namespace CryptoExchange.Net.Objects
if(partialEndpointLimits.Any(p => p.IgnoreOtherRateLimits))
return new CallResult<int>(totalWaitTime);
ApiKeyRateLimiter? apiLimit;
List<ApiKeyRateLimiter> apiLimits;
lock (_limiterLock)
apiLimit = _limiters.OfType<ApiKeyRateLimiter>().SingleOrDefault(h => h.Type == RateLimitType.ApiKey);
if (apiLimit != null)
apiLimits = _limiters.OfType<ApiKeyRateLimiter>().Where(h => h.Type == RateLimitType.ApiKey).ToList();
foreach (var apiLimit in apiLimits)
{
if(apiKey == null)
{
@@ -206,13 +206,13 @@ namespace CryptoExchange.Net.Objects
}
}
if ((signed || apiLimit?.OnlyForSignedRequests == false) && apiLimit?.IgnoreTotalRateLimit == true)
if ((signed || apiLimits.All(l => !l.OnlyForSignedRequests)) && apiLimits.Any(l => l.IgnoreTotalRateLimit))
return new CallResult<int>(totalWaitTime);
TotalRateLimiter? totalLimit;
List<TotalRateLimiter> totalLimits;
lock (_limiterLock)
totalLimit = _limiters.OfType<TotalRateLimiter>().SingleOrDefault();
if (totalLimit != null)
totalLimits = _limiters.OfType<TotalRateLimiter>().ToList();
foreach(var totalLimit in totalLimits)
{
var waitResult = await ProcessTopic(logger, totalLimit, endpoint, requestWeight, limitBehaviour, ct).ConfigureAwait(false);
if (!waitResult)
@@ -278,7 +278,7 @@ namespace CryptoExchange.Net.Sockets
return;
var bytes = Parameters.Encoding.GetBytes(data);
_logger.Log(LogLevel.Trace, $"Socket {Id} - msg {id} - Adding {bytes.Length} to send buffer");
_logger.Log(LogLevel.Trace, $"Socket {Id} - msg {id} - Adding {bytes.Length} bytes to send buffer");
_sendBuffer.Enqueue(new SendItem { Id = id, Weight = weight, Bytes = bytes });
_sendEvent.Set();
}
@@ -291,10 +291,13 @@ namespace CryptoExchange.Net.Sockets
/// <param name="requestId">Id of the request sent</param>
protected virtual void HandleRequestSent(int requestId)
{
var pendingRequest = _pendingRequests.SingleOrDefault(p => p.Id == requestId);
PendingRequest pendingRequest;
lock (_pendingRequests)
pendingRequest = _pendingRequests.SingleOrDefault(p => p.Id == requestId);
if (pendingRequest == null)
{
_logger.Log(LogLevel.Debug, $"Socket {SocketId} - msg {requestId} - message sent, but not pending");
_logger.Log(LogLevel.Debug, $"Socket {SocketId} - msg {requestId} - message sent, but not pending");
return;
}
@@ -380,7 +383,7 @@ namespace CryptoExchange.Net.Sockets
"Data from this socket may arrive late or not at all if message processing is continuously slow.");
}
_logger.Log(LogLevel.Trace, $"Socket {SocketId}{(subscription == null ? "" : " subscription " + subscription!.Id)} message processed in {(int)total.TotalMilliseconds}ms, ({(int)userProcessTime.TotalMilliseconds}ms user code)");
_logger.Log(LogLevel.Trace, $"Socket {SocketId}{(subscription == null ? "" : " subscription " + subscription!.Id)} message processed in {(int)total.TotalMilliseconds}ms ({(int)userProcessTime.TotalMilliseconds}ms user code)");
}
/// <summary>
+11 -2
View File
@@ -1,5 +1,5 @@
# CryptoExchange.Net
[![.NET](https://github.com/JKorf/CryptoExchange.Net/actions/workflows/dotnet.yml/badge.svg?branch=master)](https://github.com/JKorf/CryptoExchange.Net/actions/workflows/dotnet.yml) ![Nuget version](https://img.shields.io/nuget/v/CryptoExchange.Net.svg) ![Nuget downloads](https://img.shields.io/nuget/dt/CryptoExchange.Net.svg)
[![.NET](https://github.com/JKorf/CryptoExchange.Net/actions/workflows/dotnet.yml/badge.svg?branch=master)](https://github.com/JKorf/CryptoExchange.Net/actions/workflows/dotnet.yml) [![Nuget version](https://img.shields.io/nuget/v/CryptoExchange.Net.svg)](https://www.nuget.org/packages/CryptoExchange.Net) [![Nuget downloads](https://img.shields.io/nuget/dt/CryptoExchange.Net.svg)](https://www.nuget.org/packages/CryptoExchange.Net)
CryptoExchange.Net is a base package which can be used to easily implement crypto currency exchange API's in C#. This library offers base classes for creating rest and websocket clients, and includes additional features like an automatically synchronizing order book implementation, error handling and automatic reconnects on websocket connections.
@@ -18,7 +18,6 @@ Use one of the following following referral links to signup to a new exchange to
[Bittrex](https://bittrex.com/discover/join?referralCode=TST-DJM-CSX)
[Bybit](https://partner.bybit.com/b/jkorf)
[CoinEx](https://www.coinex.com/register?refer_code=hd6gn)
[FTX](https://ftx.com/referrals#a=31620192)
[Huobi](https://www.huobi.com/en-us/v/register/double-invite/?inviter_id=11343840&invite_code=fxp93)
[Kucoin](https://www.kucoin.com/ucenter/signup?rcode=RguMux)
@@ -32,6 +31,16 @@ 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 6.1.3 - 18 Sep 2023
* Fix for concurrency exception in socket subscription
* Version 6.1.2 - 11 Sep 2023
* Added support for multiple of the same ratelimiting type in the same rate limiter
* Fixed nullreference on rate limit error if no Retry-After header is returned
* Version 6.1.1 - 04 Sep 2023
* Fixes for json converters
* Version 6.1.0 - 24 Aug 2023
* Added support for ratelimiting on socket connections
* Added rest ratelimit handling and parsing
+1 -1
View File
@@ -3,7 +3,7 @@ title: Home
nav_order: 1
---
[![.NET](https://github.com/JKorf/CryptoExchange.Net/actions/workflows/dotnet.yml/badge.svg?branch=master)](https://github.com/JKorf/CryptoExchange.Net/actions/workflows/dotnet.yml) ![Nuget version](https://img.shields.io/nuget/v/CryptoExchange.Net.svg) ![Nuget downloads](https://img.shields.io/nuget/dt/CryptoExchange.Net.svg)
[![.NET](https://github.com/JKorf/CryptoExchange.Net/actions/workflows/dotnet.yml/badge.svg?branch=master)](https://github.com/JKorf/CryptoExchange.Net/actions/workflows/dotnet.yml) [![Nuget version](https://img.shields.io/nuget/v/CryptoExchange.Net.svg)](https://www.nuget.org/packages/CryptoExchange.Net) [![Nuget downloads](https://img.shields.io/nuget/dt/CryptoExchange.Net.svg)](https://www.nuget.org/packages/CryptoExchange.Net)
The CryptoExchange.Net library is a base package for exchange API implementations. It offers base classes for creating clients for exchange API's. Basing exchange implementation on the common CryptoExchange.Net library allows for ease of implementation for new exchanges, as only the endpoints and models have to implemented, but not all systems around requests and connections, and it makes it easier for users to implement a new library in their code base as all base principles and configuration are the same for different exchanges.