Skip to content

Commit

Permalink
System.Text.Json update
Browse files Browse the repository at this point in the history
Updated from Newtonsoft.Json to System.Text.Json
Added CryptoLoan endpoints
Added client side ratelimiting
Removed deprecated V1/V2/V3 endpoints, models and enums
  • Loading branch information
JKorf authored Jan 7, 2025
1 parent fdfe479 commit e1edc9f
Show file tree
Hide file tree
Showing 370 changed files with 3,100 additions and 13,981 deletions.
6 changes: 3 additions & 3 deletions ByBit.Net/Bybit.Net.csproj
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;netstandard2.1</TargetFrameworks>
<Nullable>enable</Nullable>
<LangVersion>10.0</LangVersion>
<LangVersion>12.0</LangVersion>
</PropertyGroup>
<PropertyGroup>
<PackageId>Bybit.Net</PackageId>
Expand Down Expand Up @@ -48,7 +48,7 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="CryptoExchange.Net" Version="8.5.0" />
<PackageReference Include="CryptoExchange.Net" Version="8.6.0" />
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="9.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
Expand Down
62 changes: 17 additions & 45 deletions ByBit.Net/BybitAuthenticationProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,19 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using Bybit.Net.Clients.CopyTradingApi;
using System.Globalization;
using Bybit.Net.Clients.V5;
using System.Text;
using Newtonsoft.Json;
using Bybit.Net.Objects.Options;
using CryptoExchange.Net.Clients;
using CryptoExchange.Net.Interfaces;

namespace Bybit.Net
{
internal class BybitAuthenticationProvider : AuthenticationProvider
{
private static readonly IMessageSerializer _messageSerializer = new SystemTextJsonMessageSerializer();

public BybitAuthenticationProvider(ApiCredentials credentials) : base(credentials)
{
}
Expand Down Expand Up @@ -47,54 +48,25 @@ public override void AuthenticateRequest(
parameters = bodyParameters;
}
var timestamp = DateTimeConverter.ConvertToMilliseconds(GetTimestamp(apiClient).AddMilliseconds(-1000)).Value.ToString(CultureInfo.InvariantCulture);
if (apiClient is BybitRestClientCopyTradingApi || apiClient is BybitRestClientApi)
{
var signPayload = parameterPosition == HttpMethodParameterPosition.InUri ? uri.SetParameters(parameters, arraySerialization).Query.Replace("?", "") : requestBodyFormat == RequestBodyFormat.FormData ? parameters.ToFormData() : JsonConvert.SerializeObject(parameters);
var key = _credentials.Key!;
var recvWindow = ((BybitRestOptions)apiClient.ClientOptions).ReceiveWindow.TotalMilliseconds;
var payload = timestamp + key + recvWindow + signPayload;

string sign;
if (_credentials.CredentialType == ApiCredentialsType.Hmac)
sign = SignHMACSHA256(payload);
else
sign = SignRSASHA256(Encoding.UTF8.GetBytes(payload), SignOutputType.Base64);

var signPayload = parameterPosition == HttpMethodParameterPosition.InUri ? uri.SetParameters(parameters, arraySerialization).Query.Replace("?", "") : requestBodyFormat == RequestBodyFormat.FormData ? parameters.ToFormData() : _messageSerializer.Serialize(parameters);
var recvWindow = ((BybitRestOptions)apiClient.ClientOptions).ReceiveWindow.TotalMilliseconds;
var payload = timestamp + _credentials.Key + recvWindow + signPayload;

headers ??= new Dictionary<string, string>();
headers.Add("X-BAPI-API-KEY", key);
headers.Add("X-BAPI-SIGN", sign);
headers.Add("X-BAPI-SIGN-TYPE", "2");
headers.Add("X-BAPI-TIMESTAMP", timestamp);
headers.Add("X-BAPI-RECV-WINDOW", recvWindow.ToString());
}
string sign;
if (_credentials.CredentialType == ApiCredentialsType.Hmac)
sign = SignHMACSHA256(payload);
else
{
parameters.Add("api_key", _credentials.Key);
parameters.Add("timestamp", timestamp);
var signData = parameterPosition == HttpMethodParameterPosition.InUri ? uri.SetParameters(parameters, arraySerialization).Query.Replace("?", "") : parameters.ToFormData();
sign = SignRSASHA256(Encoding.UTF8.GetBytes(payload), SignOutputType.Base64);

string sign;
if (_credentials.CredentialType == ApiCredentialsType.Hmac)
sign = SignHMACSHA256(signData);
else
sign = SignRSASHA256(Encoding.UTF8.GetBytes(signData));
parameters.Add("sign", sign);
}
headers ??= new Dictionary<string, string>();
headers.Add("X-BAPI-API-KEY", _credentials.Key);
headers.Add("X-BAPI-SIGN", sign);
headers.Add("X-BAPI-SIGN-TYPE", "2");
headers.Add("X-BAPI-TIMESTAMP", timestamp);
headers.Add("X-BAPI-RECV-WINDOW", recvWindow.ToString());
}

public string Sign(string toSign) => SignHMACSHA256(toSign);
}

internal class BybitComparer : IComparer<string>
{
public int Compare(string x, string y)
{
if (string.Equals(x, "sign", StringComparison.Ordinal))
return 1;
if (string.Equals(y, "sign", StringComparison.Ordinal))
return -1;

return x.CompareTo(y);
}
}
}
91 changes: 89 additions & 2 deletions ByBit.Net/BybitExchange.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
using CryptoExchange.Net;
using Bybit.Net.Enums;
using CryptoExchange.Net;
using CryptoExchange.Net.Objects;
using CryptoExchange.Net.RateLimiting;
using CryptoExchange.Net.RateLimiting.Filters;
using CryptoExchange.Net.RateLimiting.Guards;
using CryptoExchange.Net.RateLimiting.Interfaces;
using CryptoExchange.Net.SharedApis;
using System;
using System.Collections.Generic;

namespace Bybit.Net
{
Expand Down Expand Up @@ -33,10 +40,14 @@ public static class BybitExchange
/// Urls to the API documentation
/// </summary>
public static string[] ApiDocsUrl { get; } = new[] {
"https://bybit-exchange.github.io/docs/v3/intro",
"https://bybit-exchange.github.io/docs/v5/intro"
};

/// <summary>
/// Type of exchange
/// </summary>
public static ExchangeType Type { get; } = ExchangeType.CEX;

/// <summary>
/// Format a base and quote asset to a Bybit recognized symbol
/// </summary>
Expand Down Expand Up @@ -65,5 +76,81 @@ public static string FormatSymbol(string baseAsset, string quoteAsset, TradingMo

return baseAsset.ToUpperInvariant() + quoteAsset.ToUpperInvariant() + (deliverTime == null ? string.Empty : (ExchangeHelpers.GetDeliveryMonthSymbol(deliverTime.Value) + deliverTime.Value.ToString("yy")));
}

/// <summary>
/// Rate limiter configuration for the Bybit API
/// </summary>
public static BybitRateLimiters RateLimiter { get; } = new BybitRateLimiters();
}

/// <summary>
/// Rate limiter configuration for the Bybit API
/// </summary>
public class BybitRateLimiters
{
private static Dictionary<AccountLevel, (int limitOther, int limitSpot)> _orderTierLimits = new Dictionary<AccountLevel, (int, int)>()
{
{ AccountLevel.Default, (10, 20) },
{ AccountLevel.Vip1, (20, 25) },
{ AccountLevel.Vip2, (40, 30) },
{ AccountLevel.Vip3, (60, 40) },
{ AccountLevel.Vip4, (60, 40) },
{ AccountLevel.Vip5, (60, 40) },
{ AccountLevel.VipSupreme, (60, 40) },
{ AccountLevel.Pro1, (150, 150) },
{ AccountLevel.Pro2, (200, 200) },
{ AccountLevel.Pro3, (250, 250) },
{ AccountLevel.Pro4, (300, 300) },
{ AccountLevel.Pro5, (300, 300) },
{ AccountLevel.Pro6, (300, 300) }
};

/// <summary>
/// Event for when a rate limit is triggered
/// </summary>
public event Action<RateLimitEvent> RateLimitTriggered;

/// <summary>
/// The Tier to use when calculating rate limits
/// </summary>
public AccountLevel Tier { get; private set; } = AccountLevel.Default;

#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
internal BybitRateLimiters()
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
{
Initialize();
}

internal (int limitSpot, int limitOther) GetOrderLimits()
{
var limits = _orderTierLimits[Tier];
return (limits.limitSpot, limits.limitOther);
}

/// <summary>
/// Configure the rate limit with a different tier
/// </summary>
/// <param name="tier"></param>
public void Configure(AccountLevel tier)
{
Tier = tier;
Initialize();
}

private void Initialize()
{
BybitRest = new RateLimitGate("Bybit Rest")
.AddGuard(new RateLimitGuard(RateLimitGuard.PerHost, Array.Empty<IGuardFilter>(), 600, TimeSpan.FromSeconds(5), RateLimitWindowType.Sliding)); // 600 requests per 5 seconds
BybitSocket = new RateLimitGate("Bybit Socket")
.AddGuard(new RateLimitGuard(RateLimitGuard.PerHost, [new LimitItemTypeFilter(RateLimitItemType.Connection)], 500, TimeSpan.FromMinutes(5), RateLimitWindowType.Sliding)); // 500 connections per 5 minutes
BybitRest.RateLimitTriggered += (x) => RateLimitTriggered?.Invoke(x);
BybitSocket.RateLimitTriggered += (x) => RateLimitTriggered?.Invoke(x);
}


internal IRateLimitGate BybitRest { get; private set; }
internal IRateLimitGate BybitSocket { get; private set; }

}
}
23 changes: 1 addition & 22 deletions ByBit.Net/Clients/BybitRestClient.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
using Bybit.Net.Clients.CopyTradingApi;
using Bybit.Net.Interfaces.Clients;
using Bybit.Net.Interfaces.Clients.CopyTradingApi;
using Bybit.Net.Clients.SpotApi.v3;
using Bybit.Net.Interfaces.Clients.SpotApi.v3;
using Bybit.Net.Interfaces.Clients.DerivativesApi;
using Bybit.Net.Clients.DerivativesApi;
using Bybit.Net.Interfaces.Clients;
using CryptoExchange.Net.Authentication;
using System.Net.Http;
using Bybit.Net.Objects.Options;
Expand All @@ -19,12 +13,6 @@ namespace Bybit.Net.Clients
/// <inheritdoc cref="IBybitRestClient" />
public class BybitRestClient : BaseRestClient, IBybitRestClient
{
/// <inheritdoc />
public IBybitRestClientSpotApiV3 SpotApiV3 { get; }
/// <inheritdoc />
public IBybitRestClientCopyTradingApi CopyTradingApi { get; }
/// <inheritdoc />
public IBybitRestClientDerivativesApi DerivativesApi { get; }
/// <inheritdoc />
public Interfaces.Clients.V5.IBybitRestClientApi V5Api { get; }

Expand All @@ -49,9 +37,6 @@ public BybitRestClient(HttpClient? httpClient, ILoggerFactory? loggerFactory, IO
{
Initialize(options.Value);

SpotApiV3 = AddApiClient(new BybitRestClientSpotApiV3(_logger, httpClient, options.Value));
CopyTradingApi = AddApiClient(new BybitRestClientCopyTradingApi(_logger, httpClient, options.Value));
DerivativesApi = AddApiClient(new BybitRestClientDerivativesApi(_logger, httpClient, options.Value));
V5Api = AddApiClient(new V5.BybitRestClientApi(_logger, httpClient, options.Value));
}

Expand All @@ -60,9 +45,6 @@ public BybitRestClient(HttpClient? httpClient, ILoggerFactory? loggerFactory, IO
/// <inheritdoc />
public void SetOptions(UpdateOptions options)
{
SpotApiV3.SetOptions(options);
CopyTradingApi.SetOptions(options);
DerivativesApi.SetOptions(options);
V5Api.SetOptions(options);
}

Expand All @@ -78,9 +60,6 @@ public static void SetDefaultOptions(Action<BybitRestOptions> optionsDelegate)
/// <inheritdoc />
public void SetApiCredentials(ApiCredentials credentials)
{
SpotApiV3.SetApiCredentials(credentials);
CopyTradingApi.SetApiCredentials(credentials);
DerivativesApi.SetApiCredentials(credentials);
V5Api.SetApiCredentials(credentials);
}
}
Expand Down
31 changes: 1 addition & 30 deletions ByBit.Net/Clients/BybitSocketClient.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,10 @@
using System;
using Bybit.Net.Interfaces.Clients;
using Bybit.Net.Interfaces.Clients.SpotApi.v3;
using Bybit.Net.Interfaces.Clients.DerivativesApi.UnifiedMarginApi;
using Bybit.Net.Interfaces.Clients.DerivativesApi.ContractApi;
using Bybit.Net.Interfaces.Clients.DerivativesApi;
using CryptoExchange.Net.Authentication;
using Bybit.Net.Clients.V5;
using Bybit.Net.Interfaces.Clients.V5;
using Microsoft.Extensions.Logging;
using Bybit.Net.Objects.Options;
using Bybit.Net.Clients.DerivativesApi;
using Bybit.Net.Clients.DerivativesApi.ContractApi;
using Bybit.Net.Clients.DerivativesApi.UnifiedMarginApi;
using Bybit.Net.Clients.SpotApi.v3;
using CryptoExchange.Net.Clients;
using Microsoft.Extensions.Options;
using CryptoExchange.Net.Objects.Options;
Expand All @@ -22,14 +14,6 @@ namespace Bybit.Net.Clients
/// <inheritdoc cref="IBybitSocketClient" />
public class BybitSocketClient : BaseSocketClient, IBybitSocketClient
{
/// <inheritdoc />
public IBybitSocketClientSpotApiV3 SpotV3Api { get; }
/// <inheritdoc />
public IBybitSocketClientDerivativesPublicApi DerivativesApi { get; }
/// <inheritdoc />
public IBybitSocketClientUnifiedMarginApi UnifiedMarginApi { get; }
/// <inheritdoc />
public IBybitSocketClientContractApi ContractApi { get; }
/// <inheritdoc />
public IBybitSocketClientSpotApi V5SpotApi { get; }
/// <inheritdoc />
Expand Down Expand Up @@ -59,12 +43,6 @@ public BybitSocketClient(IOptions<BybitSocketOptions> options, ILoggerFactory? l
{
Initialize(options.Value);

SpotV3Api = AddApiClient(new BybitSocketClientSpotApiV3(_logger, options.Value));

DerivativesApi = AddApiClient(new BybitSocketClientDerivativesPublicApi(_logger, options.Value));
UnifiedMarginApi = AddApiClient(new BybitSocketClientUnifiedMarginApi(_logger, options.Value));
ContractApi = AddApiClient(new BybitSocketClientContractApi(_logger, options.Value));

V5SpotApi = AddApiClient(new BybitSocketClientSpotApi(_logger, options.Value));
V5InverseApi = AddApiClient(new BybitSocketClientInverseApi(_logger, options.Value));
V5LinearApi = AddApiClient(new BybitSocketClientLinearApi(_logger, options.Value));
Expand All @@ -75,10 +53,6 @@ public BybitSocketClient(IOptions<BybitSocketOptions> options, ILoggerFactory? l
/// <inheritdoc />
public void SetOptions(UpdateOptions options)
{
SpotV3Api.SetOptions(options);
DerivativesApi.SetOptions(options);
UnifiedMarginApi.SetOptions(options);
ContractApi.SetOptions(options);
V5SpotApi.SetOptions(options);
V5InverseApi.SetOptions(options);
V5LinearApi.SetOptions(options);
Expand All @@ -98,12 +72,9 @@ public static void SetDefaultOptions(Action<BybitSocketOptions> optionsDelegate)
/// <inheritdoc />
public void SetApiCredentials(ApiCredentials credentials)
{
SpotV3Api.SetApiCredentials(credentials);
DerivativesApi.SetApiCredentials(credentials);
UnifiedMarginApi.SetApiCredentials(credentials);
ContractApi.SetApiCredentials(credentials);
V5LinearApi.SetApiCredentials(credentials);
V5OptionsApi.SetApiCredentials(credentials);
V5InverseApi.SetApiCredentials(credentials);
V5PrivateApi.SetApiCredentials(credentials);
V5SpotApi.SetApiCredentials(credentials);
}
Expand Down
Loading

0 comments on commit e1edc9f

Please sign in to comment.