mirror of
https://github.com/JKorf/CryptoExchange.Net
synced 2025-06-07 16:06:15 +00:00
Compare commits
12 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
3e635cf0fe | ||
|
1425c66c69 | ||
|
fc3b7cc75b | ||
|
2cc2dc6ceb | ||
|
7da8cedf66 | ||
|
2cf10668dd | ||
|
f1342b5ff2 | ||
|
a04b636a11 | ||
|
e4637ad295 | ||
|
3a1e43dabe | ||
|
10da1a7bfe | ||
|
37320ca862 |
@ -7,6 +7,7 @@ using System.Text.Json.Serialization;
|
|||||||
using NUnit.Framework.Legacy;
|
using NUnit.Framework.Legacy;
|
||||||
using CryptoExchange.Net.Converters;
|
using CryptoExchange.Net.Converters;
|
||||||
using CryptoExchange.Net.Testing.Comparers;
|
using CryptoExchange.Net.Testing.Comparers;
|
||||||
|
using CryptoExchange.Net.SharedApis;
|
||||||
|
|
||||||
namespace CryptoExchange.Net.UnitTests
|
namespace CryptoExchange.Net.UnitTests
|
||||||
{
|
{
|
||||||
@ -298,6 +299,40 @@ namespace CryptoExchange.Net.UnitTests
|
|||||||
Assert.That(deserialized.Prop8.Prop31, Is.EqualTo(5));
|
Assert.That(deserialized.Prop8.Prop31, Is.EqualTo(5));
|
||||||
Assert.That(deserialized.Prop8.Prop32, Is.EqualTo("101"));
|
Assert.That(deserialized.Prop8.Prop32, Is.EqualTo("101"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TestCase(TradingMode.Spot, "ETH", "USDT", null)]
|
||||||
|
[TestCase(TradingMode.PerpetualLinear, "ETH", "USDT", null)]
|
||||||
|
[TestCase(TradingMode.DeliveryLinear, "ETH", "USDT", 1748432430)]
|
||||||
|
public void TestSharedSymbolConversion(TradingMode tradingMode, string baseAsset, string quoteAsset, int? deliverTime)
|
||||||
|
{
|
||||||
|
DateTime? time = deliverTime == null ? null : DateTimeConverter.ParseFromDouble(deliverTime.Value);
|
||||||
|
var symbol = new SharedSymbol(tradingMode, baseAsset, quoteAsset, time);
|
||||||
|
|
||||||
|
var serialized = JsonSerializer.Serialize(symbol);
|
||||||
|
var restored = JsonSerializer.Deserialize<SharedSymbol>(serialized);
|
||||||
|
|
||||||
|
Assert.That(restored.TradingMode, Is.EqualTo(symbol.TradingMode));
|
||||||
|
Assert.That(restored.BaseAsset, Is.EqualTo(symbol.BaseAsset));
|
||||||
|
Assert.That(restored.QuoteAsset, Is.EqualTo(symbol.QuoteAsset));
|
||||||
|
Assert.That(restored.DeliverTime, Is.EqualTo(symbol.DeliverTime));
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase(0.1, null, null)]
|
||||||
|
[TestCase(0.1, 0.1, null)]
|
||||||
|
[TestCase(0.1, 0.1, 0.1)]
|
||||||
|
[TestCase(null, 0.1, null)]
|
||||||
|
[TestCase(null, 0.1, 0.1)]
|
||||||
|
public void TestSharedQuantityConversion(double? baseQuantity, double? quoteQuantity, double? contractQuantity)
|
||||||
|
{
|
||||||
|
var symbol = new SharedOrderQuantity((decimal?)baseQuantity, (decimal?)quoteQuantity, (decimal?)contractQuantity);
|
||||||
|
|
||||||
|
var serialized = JsonSerializer.Serialize(symbol);
|
||||||
|
var restored = JsonSerializer.Deserialize<SharedOrderQuantity>(serialized);
|
||||||
|
|
||||||
|
Assert.That(restored.QuantityInBaseAsset, Is.EqualTo(symbol.QuantityInBaseAsset));
|
||||||
|
Assert.That(restored.QuantityInQuoteAsset, Is.EqualTo(symbol.QuantityInQuoteAsset));
|
||||||
|
Assert.That(restored.QuantityInContracts, Is.EqualTo(symbol.QuantityInContracts));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class STJDecimalObject
|
public class STJDecimalObject
|
||||||
|
@ -114,7 +114,7 @@ namespace CryptoExchange.Net.UnitTests.TestImplementations
|
|||||||
|
|
||||||
public CallResult ConnectSocketSub(SocketConnection sub)
|
public CallResult ConnectSocketSub(SocketConnection sub)
|
||||||
{
|
{
|
||||||
return ConnectSocketAsync(sub).Result;
|
return ConnectSocketAsync(sub, default).Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string GetListenerIdentifier(IMessageAccessor message)
|
public override string GetListenerIdentifier(IMessageAccessor message)
|
||||||
|
@ -244,7 +244,7 @@ namespace CryptoExchange.Net.Clients
|
|||||||
|
|
||||||
var needsConnecting = !socketConnection.Connected;
|
var needsConnecting = !socketConnection.Connected;
|
||||||
|
|
||||||
var connectResult = await ConnectIfNeededAsync(socketConnection, subscription.Authenticated).ConfigureAwait(false);
|
var connectResult = await ConnectIfNeededAsync(socketConnection, subscription.Authenticated, ct).ConfigureAwait(false);
|
||||||
if (!connectResult)
|
if (!connectResult)
|
||||||
return new CallResult<UpdateSubscription>(connectResult.Error!);
|
return new CallResult<UpdateSubscription>(connectResult.Error!);
|
||||||
|
|
||||||
@ -268,7 +268,7 @@ namespace CryptoExchange.Net.Clients
|
|||||||
if (subQuery != null)
|
if (subQuery != null)
|
||||||
{
|
{
|
||||||
// Send the request and wait for answer
|
// Send the request and wait for answer
|
||||||
var subResult = await socketConnection.SendAndWaitQueryAsync(subQuery, waitEvent).ConfigureAwait(false);
|
var subResult = await socketConnection.SendAndWaitQueryAsync(subQuery, waitEvent, ct).ConfigureAwait(false);
|
||||||
if (!subResult)
|
if (!subResult)
|
||||||
{
|
{
|
||||||
waitEvent?.Set();
|
waitEvent?.Set();
|
||||||
@ -352,7 +352,7 @@ namespace CryptoExchange.Net.Clients
|
|||||||
released = true;
|
released = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
var connectResult = await ConnectIfNeededAsync(socketConnection, query.Authenticated).ConfigureAwait(false);
|
var connectResult = await ConnectIfNeededAsync(socketConnection, query.Authenticated, ct).ConfigureAwait(false);
|
||||||
if (!connectResult)
|
if (!connectResult)
|
||||||
return new CallResult<THandlerResponse>(connectResult.Error!);
|
return new CallResult<THandlerResponse>(connectResult.Error!);
|
||||||
}
|
}
|
||||||
@ -379,13 +379,14 @@ namespace CryptoExchange.Net.Clients
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="socket">The connection to check</param>
|
/// <param name="socket">The connection to check</param>
|
||||||
/// <param name="authenticated">Whether the socket should authenticated</param>
|
/// <param name="authenticated">Whether the socket should authenticated</param>
|
||||||
|
/// <param name="ct">Cancellation token</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
protected virtual async Task<CallResult> ConnectIfNeededAsync(SocketConnection socket, bool authenticated)
|
protected virtual async Task<CallResult> ConnectIfNeededAsync(SocketConnection socket, bool authenticated, CancellationToken ct)
|
||||||
{
|
{
|
||||||
if (socket.Connected)
|
if (socket.Connected)
|
||||||
return CallResult.SuccessResult;
|
return CallResult.SuccessResult;
|
||||||
|
|
||||||
var connectResult = await ConnectSocketAsync(socket).ConfigureAwait(false);
|
var connectResult = await ConnectSocketAsync(socket, ct).ConfigureAwait(false);
|
||||||
if (!connectResult)
|
if (!connectResult)
|
||||||
return connectResult;
|
return connectResult;
|
||||||
|
|
||||||
@ -579,10 +580,11 @@ namespace CryptoExchange.Net.Clients
|
|||||||
/// Connect a socket
|
/// Connect a socket
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="socketConnection">The socket to connect</param>
|
/// <param name="socketConnection">The socket to connect</param>
|
||||||
|
/// <param name="ct">Cancellation token</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
protected virtual async Task<CallResult> ConnectSocketAsync(SocketConnection socketConnection)
|
protected virtual async Task<CallResult> ConnectSocketAsync(SocketConnection socketConnection, CancellationToken ct)
|
||||||
{
|
{
|
||||||
var connectResult = await socketConnection.ConnectAsync().ConfigureAwait(false);
|
var connectResult = await socketConnection.ConnectAsync(ct).ConfigureAwait(false);
|
||||||
if (connectResult)
|
if (connectResult)
|
||||||
{
|
{
|
||||||
socketConnections.TryAdd(socketConnection.SocketId, socketConnection);
|
socketConnections.TryAdd(socketConnection.SocketId, socketConnection);
|
||||||
@ -714,7 +716,7 @@ namespace CryptoExchange.Net.Clients
|
|||||||
if (!socketResult)
|
if (!socketResult)
|
||||||
return socketResult.AsDataless();
|
return socketResult.AsDataless();
|
||||||
|
|
||||||
var connectResult = await ConnectIfNeededAsync(socketResult.Data, item.Authenticated).ConfigureAwait(false);
|
var connectResult = await ConnectIfNeededAsync(socketResult.Data, item.Authenticated, default).ConfigureAwait(false);
|
||||||
if (!connectResult)
|
if (!connectResult)
|
||||||
return new CallResult(connectResult.Error!);
|
return new CallResult(connectResult.Error!);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,60 @@
|
|||||||
|
using CryptoExchange.Net.SharedApis;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace CryptoExchange.Net.Converters.SystemTextJson
|
||||||
|
{
|
||||||
|
internal class SharedQuantityConverter : SharedQuantityReferenceConverter<SharedQuantity> { }
|
||||||
|
internal class SharedOrderQuantityConverter : SharedQuantityReferenceConverter<SharedOrderQuantity> { }
|
||||||
|
|
||||||
|
internal class SharedQuantityReferenceConverter<T> : JsonConverter<T> where T: SharedQuantityReference, new()
|
||||||
|
{
|
||||||
|
public override T? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
if (reader.TokenType != JsonTokenType.StartArray)
|
||||||
|
throw new Exception("");
|
||||||
|
|
||||||
|
reader.Read(); // Start array
|
||||||
|
var baseQuantity = reader.TokenType == JsonTokenType.Null ? (decimal?)null : reader.GetDecimal();
|
||||||
|
reader.Read();
|
||||||
|
var quoteQuantity = reader.TokenType == JsonTokenType.Null ? (decimal?)null : reader.GetDecimal();
|
||||||
|
reader.Read();
|
||||||
|
var contractQuantity = reader.TokenType == JsonTokenType.Null ? (decimal?)null : reader.GetDecimal();
|
||||||
|
reader.Read();
|
||||||
|
|
||||||
|
if (reader.TokenType != JsonTokenType.EndArray)
|
||||||
|
throw new Exception("");
|
||||||
|
|
||||||
|
reader.Read(); // End array
|
||||||
|
|
||||||
|
var result = new T();
|
||||||
|
result.QuantityInBaseAsset = baseQuantity;
|
||||||
|
result.QuantityInQuoteAsset = quoteQuantity;
|
||||||
|
result.QuantityInContracts = contractQuantity;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
writer.WriteStartArray();
|
||||||
|
if (value.QuantityInBaseAsset == null)
|
||||||
|
writer.WriteNullValue();
|
||||||
|
else
|
||||||
|
writer.WriteNumberValue(value.QuantityInBaseAsset.Value);
|
||||||
|
|
||||||
|
if (value.QuantityInQuoteAsset == null)
|
||||||
|
writer.WriteNullValue();
|
||||||
|
else
|
||||||
|
writer.WriteNumberValue(value.QuantityInQuoteAsset.Value);
|
||||||
|
|
||||||
|
if (value.QuantityInContracts == null)
|
||||||
|
writer.WriteNullValue();
|
||||||
|
else
|
||||||
|
writer.WriteNumberValue(value.QuantityInContracts.Value);
|
||||||
|
writer.WriteEndArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
using CryptoExchange.Net.SharedApis;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace CryptoExchange.Net.Converters.SystemTextJson
|
||||||
|
{
|
||||||
|
internal class SharedSymbolConverter : JsonConverter<SharedSymbol>
|
||||||
|
{
|
||||||
|
public override SharedSymbol? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
if (reader.TokenType != JsonTokenType.StartArray)
|
||||||
|
throw new Exception("");
|
||||||
|
|
||||||
|
reader.Read(); // Start array
|
||||||
|
var tradingMode = (TradingMode)Enum.Parse(typeof(TradingMode), reader.GetString()!);
|
||||||
|
reader.Read();
|
||||||
|
var baseAsset = reader.GetString()!;
|
||||||
|
reader.Read();
|
||||||
|
var quoteAsset = reader.GetString()!;
|
||||||
|
reader.Read();
|
||||||
|
var timeStr = reader.GetString()!;
|
||||||
|
var deliverTime = string.IsNullOrEmpty(timeStr) ? (DateTime?)null : DateTime.Parse(timeStr);
|
||||||
|
reader.Read();
|
||||||
|
|
||||||
|
if (reader.TokenType != JsonTokenType.EndArray)
|
||||||
|
throw new Exception("");
|
||||||
|
|
||||||
|
reader.Read(); // End array
|
||||||
|
|
||||||
|
return new SharedSymbol(tradingMode, baseAsset, quoteAsset, deliverTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(Utf8JsonWriter writer, SharedSymbol value, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
writer.WriteStartArray();
|
||||||
|
writer.WriteStringValue(value.TradingMode.ToString());
|
||||||
|
writer.WriteStringValue(value.BaseAsset);
|
||||||
|
writer.WriteStringValue(value.QuoteAsset);
|
||||||
|
writer.WriteStringValue(value.DeliverTime?.ToString());
|
||||||
|
writer.WriteEndArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -6,9 +6,9 @@
|
|||||||
<PackageId>CryptoExchange.Net</PackageId>
|
<PackageId>CryptoExchange.Net</PackageId>
|
||||||
<Authors>JKorf</Authors>
|
<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>
|
<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>9.0.0</PackageVersion>
|
<PackageVersion>9.1.0</PackageVersion>
|
||||||
<AssemblyVersion>9.0.0</AssemblyVersion>
|
<AssemblyVersion>9.1.0</AssemblyVersion>
|
||||||
<FileVersion>9.0.0</FileVersion>
|
<FileVersion>9.1.0</FileVersion>
|
||||||
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
|
<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>
|
<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>
|
<RepositoryType>git</RepositoryType>
|
||||||
@ -27,7 +27,7 @@
|
|||||||
<None Include="Icon\icon.png" Pack="true" PackagePath="\" />
|
<None Include="Icon\icon.png" Pack="true" PackagePath="\" />
|
||||||
<None Include="..\README.md" Pack="true" PackagePath="\" />
|
<None Include="..\README.md" Pack="true" PackagePath="\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Label="AOT" Condition=" '$(TargetFramework)' == 'NET8_0' Or '$(TargetFramework)' == 'NET9_0' ">
|
<PropertyGroup Label="AOT" Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net7.0'))">
|
||||||
<IsAotCompatible>true</IsAotCompatible>
|
<IsAotCompatible>true</IsAotCompatible>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Label="Deterministic Build" Condition="'$(Configuration)' == 'Release'">
|
<PropertyGroup Label="Deterministic Build" Condition="'$(Configuration)' == 'Release'">
|
||||||
@ -37,12 +37,6 @@
|
|||||||
<EmbedUntrackedSources>true</EmbedUntrackedSources>
|
<EmbedUntrackedSources>true</EmbedUntrackedSources>
|
||||||
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
|
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup Label="Deterministic Build" Condition="'$(Configuration)' == 'Release'">
|
|
||||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0">
|
|
||||||
<PrivateAssets>all</PrivateAssets>
|
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
|
||||||
</PackageReference>
|
|
||||||
</ItemGroup>
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<DocumentationFile>CryptoExchange.Net.xml</DocumentationFile>
|
<DocumentationFile>CryptoExchange.Net.xml</DocumentationFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
@ -57,10 +51,11 @@
|
|||||||
</PackageReference>
|
</PackageReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.5" />
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.0" />
|
<PackageReference Include="System.Text.Json" Version="9.0.5" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.0" />
|
</ItemGroup>
|
||||||
<PackageReference Include="System.Text.Json" Version="9.0.0" />
|
<ItemGroup Label="Transitive Client Packages">
|
||||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="9.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="9.0.5" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.5" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
@ -1,6 +1,7 @@
|
|||||||
using CryptoExchange.Net.Objects;
|
using CryptoExchange.Net.Objects;
|
||||||
using System;
|
using System;
|
||||||
using System.Net.WebSockets;
|
using System.Net.WebSockets;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace CryptoExchange.Net.Interfaces
|
namespace CryptoExchange.Net.Interfaces
|
||||||
@ -75,7 +76,7 @@ namespace CryptoExchange.Net.Interfaces
|
|||||||
/// Connect the socket
|
/// Connect the socket
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<CallResult> ConnectAsync();
|
Task<CallResult> ConnectAsync(CancellationToken ct);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Send data
|
/// Send data
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -8,6 +8,7 @@ namespace CryptoExchange.Net.Logging.Extensions
|
|||||||
{
|
{
|
||||||
private static readonly Action<ILogger, int, Exception?> _connecting;
|
private static readonly Action<ILogger, int, Exception?> _connecting;
|
||||||
private static readonly Action<ILogger, int, string, Exception?> _connectionFailed;
|
private static readonly Action<ILogger, int, string, Exception?> _connectionFailed;
|
||||||
|
private static readonly Action<ILogger, int, Exception?> _connectingCanceled;
|
||||||
private static readonly Action<ILogger, int, Uri, Exception?> _connected;
|
private static readonly Action<ILogger, int, Uri, Exception?> _connected;
|
||||||
private static readonly Action<ILogger, int, Exception?> _startingProcessing;
|
private static readonly Action<ILogger, int, Exception?> _startingProcessing;
|
||||||
private static readonly Action<ILogger, int, Exception?> _finishedProcessing;
|
private static readonly Action<ILogger, int, Exception?> _finishedProcessing;
|
||||||
@ -189,6 +190,12 @@ namespace CryptoExchange.Net.Logging.Extensions
|
|||||||
new EventId(1030, "SocketPingTimeout"),
|
new EventId(1030, "SocketPingTimeout"),
|
||||||
"[Sckt {Id}] ping frame timeout; reconnecting socket");
|
"[Sckt {Id}] ping frame timeout; reconnecting socket");
|
||||||
|
|
||||||
|
_connectingCanceled = LoggerMessage.Define<int>(
|
||||||
|
LogLevel.Debug,
|
||||||
|
new EventId(1031, "ConnectingCanceled"),
|
||||||
|
"[Sckt {SocketId}] connecting canceled");
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SocketConnecting(
|
public static void SocketConnecting(
|
||||||
@ -370,5 +377,11 @@ namespace CryptoExchange.Net.Logging.Extensions
|
|||||||
{
|
{
|
||||||
_socketPingTimeout(logger, socketId, null);
|
_socketPingTimeout(logger, socketId, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void SocketConnectingCanceled(
|
||||||
|
this ILogger logger, int socketId)
|
||||||
|
{
|
||||||
|
_connectingCanceled(logger, socketId, null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
using System;
|
using CryptoExchange.Net.Converters.SystemTextJson;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace CryptoExchange.Net.SharedApis
|
namespace CryptoExchange.Net.SharedApis
|
||||||
{
|
{
|
||||||
@ -25,7 +27,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected SharedQuantityReference(decimal? baseAssetQuantity, decimal? quoteAssetQuantity, decimal? contractQuantity)
|
internal SharedQuantityReference(decimal? baseAssetQuantity, decimal? quoteAssetQuantity, decimal? contractQuantity)
|
||||||
{
|
{
|
||||||
QuantityInBaseAsset = baseAssetQuantity;
|
QuantityInBaseAsset = baseAssetQuantity;
|
||||||
QuantityInQuoteAsset = quoteAssetQuantity;
|
QuantityInQuoteAsset = quoteAssetQuantity;
|
||||||
@ -36,6 +38,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Quantity for an order
|
/// Quantity for an order
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[JsonConverter(typeof(SharedQuantityConverter))]
|
||||||
public record SharedQuantity : SharedQuantityReference
|
public record SharedQuantity : SharedQuantityReference
|
||||||
{
|
{
|
||||||
private SharedQuantity(decimal? baseAssetQuantity, decimal? quoteAssetQuantity, decimal? contractQuantity)
|
private SharedQuantity(decimal? baseAssetQuantity, decimal? quoteAssetQuantity, decimal? contractQuantity)
|
||||||
@ -43,6 +46,11 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ctor
|
||||||
|
/// </summary>
|
||||||
|
public SharedQuantity() : base(null, null, null) { }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specify quantity in base asset
|
/// Specify quantity in base asset
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -98,6 +106,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Order quantity
|
/// Order quantity
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[JsonConverter(typeof(SharedOrderQuantityConverter))]
|
||||||
public record SharedOrderQuantity : SharedQuantityReference
|
public record SharedOrderQuantity : SharedQuantityReference
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
using CryptoExchange.Net.Objects;
|
using CryptoExchange.Net.Converters.SystemTextJson;
|
||||||
|
using CryptoExchange.Net.Objects;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace CryptoExchange.Net.SharedApis
|
namespace CryptoExchange.Net.SharedApis
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A symbol representation based on a base and quote asset
|
/// A symbol representation based on a base and quote asset
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[JsonConverter(typeof(SharedSymbolConverter))]
|
||||||
public record SharedSymbol
|
public record SharedSymbol
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -166,9 +166,9 @@ namespace CryptoExchange.Net.Sockets
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public virtual async Task<CallResult> ConnectAsync()
|
public virtual async Task<CallResult> ConnectAsync(CancellationToken ct)
|
||||||
{
|
{
|
||||||
var connectResult = await ConnectInternalAsync().ConfigureAwait(false);
|
var connectResult = await ConnectInternalAsync(ct).ConfigureAwait(false);
|
||||||
if (!connectResult)
|
if (!connectResult)
|
||||||
return connectResult;
|
return connectResult;
|
||||||
|
|
||||||
@ -215,7 +215,7 @@ namespace CryptoExchange.Net.Sockets
|
|||||||
return socket;
|
return socket;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<CallResult> ConnectInternalAsync()
|
private async Task<CallResult> ConnectInternalAsync(CancellationToken ct)
|
||||||
{
|
{
|
||||||
_logger.SocketConnecting(Id);
|
_logger.SocketConnecting(Id);
|
||||||
try
|
try
|
||||||
@ -229,12 +229,16 @@ namespace CryptoExchange.Net.Sockets
|
|||||||
}
|
}
|
||||||
|
|
||||||
using CancellationTokenSource tcs = new(TimeSpan.FromSeconds(10));
|
using CancellationTokenSource tcs = new(TimeSpan.FromSeconds(10));
|
||||||
using var linked = CancellationTokenSource.CreateLinkedTokenSource(tcs.Token, _ctsSource.Token);
|
using var linked = CancellationTokenSource.CreateLinkedTokenSource(tcs.Token, _ctsSource.Token, ct);
|
||||||
await _socket.ConnectAsync(Uri, linked.Token).ConfigureAwait(false);
|
await _socket.ConnectAsync(Uri, linked.Token).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
if (!_ctsSource.IsCancellationRequested)
|
if (ct.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
_logger.SocketConnectingCanceled(Id);
|
||||||
|
}
|
||||||
|
else if (!_ctsSource.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
// if _ctsSource was canceled this was already logged
|
// if _ctsSource was canceled this was already logged
|
||||||
_logger.SocketConnectionFailed(Id, e.Message, e);
|
_logger.SocketConnectionFailed(Id, e.Message, e);
|
||||||
@ -325,7 +329,7 @@ namespace CryptoExchange.Net.Sockets
|
|||||||
while (_sendBuffer.TryDequeue(out _)) { } // Clear send buffer
|
while (_sendBuffer.TryDequeue(out _)) { } // Clear send buffer
|
||||||
|
|
||||||
_reconnectAttempt++;
|
_reconnectAttempt++;
|
||||||
var connected = await ConnectInternalAsync().ConfigureAwait(false);
|
var connected = await ConnectInternalAsync(default).ConfigureAwait(false);
|
||||||
if (!connected)
|
if (!connected)
|
||||||
{
|
{
|
||||||
// Delay between reconnect attempts
|
// Delay between reconnect attempts
|
||||||
|
@ -79,6 +79,11 @@ namespace CryptoExchange.Net.Sockets
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public int Weight { get; }
|
public int Weight { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether the query should wait for a response or not
|
||||||
|
/// </summary>
|
||||||
|
public bool ExpectsResponse { get; set; } = true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the type the message should be deserialized to
|
/// Get the type the message should be deserialized to
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -116,10 +121,19 @@ namespace CryptoExchange.Net.Sockets
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void IsSend(TimeSpan timeout)
|
public void IsSend(TimeSpan timeout)
|
||||||
{
|
{
|
||||||
// Start timeout countdown
|
|
||||||
RequestTimestamp = DateTime.UtcNow;
|
RequestTimestamp = DateTime.UtcNow;
|
||||||
_cts = new CancellationTokenSource(timeout);
|
if (ExpectsResponse)
|
||||||
_cts.Token.Register(Timeout, false);
|
{
|
||||||
|
// Start timeout countdown
|
||||||
|
_cts = new CancellationTokenSource(timeout);
|
||||||
|
_cts.Token.Register(Timeout, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Completed = true;
|
||||||
|
Result = CallResult.SuccessResult;
|
||||||
|
_event.Set();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -571,7 +571,7 @@ namespace CryptoExchange.Net.Sockets
|
|||||||
/// Connect the websocket
|
/// Connect the websocket
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task<CallResult> ConnectAsync() => await _socket.ConnectAsync().ConfigureAwait(false);
|
public async Task<CallResult> ConnectAsync(CancellationToken ct) => await _socket.ConnectAsync(ct).ConfigureAwait(false);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Retrieve the underlying socket
|
/// Retrieve the underlying socket
|
||||||
|
@ -10,6 +10,11 @@ using System.Text.Json.Serialization;
|
|||||||
using CryptoExchange.Net.Converters;
|
using CryptoExchange.Net.Converters;
|
||||||
using CryptoExchange.Net.Converters.SystemTextJson;
|
using CryptoExchange.Net.Converters.SystemTextJson;
|
||||||
|
|
||||||
|
#pragma warning disable IL2026
|
||||||
|
#pragma warning disable IL2070
|
||||||
|
#pragma warning disable IL2075
|
||||||
|
#pragma warning disable IL3050
|
||||||
|
|
||||||
namespace CryptoExchange.Net.Testing.Comparers
|
namespace CryptoExchange.Net.Testing.Comparers
|
||||||
{
|
{
|
||||||
internal class SystemTextJsonComparer
|
internal class SystemTextJsonComparer
|
||||||
|
@ -2,10 +2,14 @@
|
|||||||
using System.Net.WebSockets;
|
using System.Net.WebSockets;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using CryptoExchange.Net.Interfaces;
|
using CryptoExchange.Net.Interfaces;
|
||||||
using CryptoExchange.Net.Objects;
|
using CryptoExchange.Net.Objects;
|
||||||
|
|
||||||
|
#pragma warning disable IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code
|
||||||
|
#pragma warning disable IL3050 // Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.
|
||||||
|
|
||||||
namespace CryptoExchange.Net.Testing.Implementations
|
namespace CryptoExchange.Net.Testing.Implementations
|
||||||
{
|
{
|
||||||
internal class TestSocket : IWebsocket
|
internal class TestSocket : IWebsocket
|
||||||
@ -47,7 +51,7 @@ namespace CryptoExchange.Net.Testing.Implementations
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<CallResult> ConnectAsync()
|
public Task<CallResult> ConnectAsync(CancellationToken ct)
|
||||||
{
|
{
|
||||||
Connected = CanConnect;
|
Connected = CanConnect;
|
||||||
return Task.FromResult(CanConnect ? new CallResult(null) : new CallResult(new CantConnectError()));
|
return Task.FromResult(CanConnect ? new CallResult(null) : new CallResult(new CantConnectError()));
|
||||||
|
@ -94,7 +94,14 @@ namespace CryptoExchange.Net.Testing
|
|||||||
|
|
||||||
TUpdate? update = default;
|
TUpdate? update = default;
|
||||||
// Invoke subscription method
|
// Invoke subscription method
|
||||||
var task = methodInvoke(_client, x => { update = x.Data; });
|
try
|
||||||
|
{
|
||||||
|
var task = methodInvoke(_client, x => { update = x.Data; });
|
||||||
|
}
|
||||||
|
catch(Exception)
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
var replaceValues = new Dictionary<string, string>();
|
var replaceValues = new Dictionary<string, string>();
|
||||||
while (true)
|
while (true)
|
||||||
|
@ -15,6 +15,11 @@ using CryptoExchange.Net.Objects;
|
|||||||
using CryptoExchange.Net.Objects.Sockets;
|
using CryptoExchange.Net.Objects.Sockets;
|
||||||
using CryptoExchange.Net.Testing.Implementations;
|
using CryptoExchange.Net.Testing.Implementations;
|
||||||
|
|
||||||
|
#pragma warning disable IL2026
|
||||||
|
#pragma warning disable IL2070
|
||||||
|
#pragma warning disable IL2075
|
||||||
|
#pragma warning disable IL3050
|
||||||
|
|
||||||
namespace CryptoExchange.Net.Testing
|
namespace CryptoExchange.Net.Testing
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -5,26 +5,27 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Binance.Net" Version="10.18.0" />
|
<PackageReference Include="Binance.Net" Version="11.0.0" />
|
||||||
<PackageReference Include="Bitfinex.Net" Version="8.1.1" />
|
<PackageReference Include="Bitfinex.Net" Version="9.0.0" />
|
||||||
<PackageReference Include="BitMart.Net" Version="1.14.0" />
|
<PackageReference Include="BitMart.Net" Version="2.0.0" />
|
||||||
<PackageReference Include="Bybit.Net" Version="4.3.2" />
|
<PackageReference Include="Bybit.Net" Version="5.0.0" />
|
||||||
<PackageReference Include="CoinEx.Net" Version="8.0.1" />
|
<PackageReference Include="CoinEx.Net" Version="9.0.1" />
|
||||||
<PackageReference Include="CryptoCom.Net" Version="1.6.0" />
|
<PackageReference Include="CryptoCom.Net" Version="2.0.0" />
|
||||||
<PackageReference Include="DeepCoin.Net" Version="1.0.0" />
|
<PackageReference Include="DeepCoin.Net" Version="2.0.0" />
|
||||||
<PackageReference Include="GateIo.Net" Version="1.20.1" />
|
<PackageReference Include="GateIo.Net" Version="2.0.0" />
|
||||||
<PackageReference Include="HyperLiquid.Net" Version="1.1.0" />
|
<PackageReference Include="HyperLiquid.Net" Version="2.0.0" />
|
||||||
<PackageReference Include="JK.BingX.Net" Version="1.21.0" />
|
<PackageReference Include="JK.BingX.Net" Version="2.0.0" />
|
||||||
<PackageReference Include="JK.Bitget.Net" Version="1.21.0" />
|
<PackageReference Include="JK.Bitget.Net" Version="2.0.0" />
|
||||||
<PackageReference Include="JK.Mexc.Net" Version="2.1.0" />
|
<PackageReference Include="JK.Mexc.Net" Version="3.0.0" />
|
||||||
<PackageReference Include="JK.OKX.Net" Version="2.15.0" />
|
<PackageReference Include="JK.OKX.Net" Version="3.0.0" />
|
||||||
<PackageReference Include="JKorf.BitMEX.Net" Version="1.1.0" />
|
<PackageReference Include="JKorf.BitMEX.Net" Version="2.0.0" />
|
||||||
<PackageReference Include="JKorf.Coinbase.Net" Version="1.8.1" />
|
<PackageReference Include="JKorf.Coinbase.Net" Version="2.0.0" />
|
||||||
<PackageReference Include="JKorf.HTX.Net" Version="6.9.0" />
|
<PackageReference Include="JKorf.HTX.Net" Version="7.0.0" />
|
||||||
<PackageReference Include="KrakenExchange.Net" Version="5.7.1" />
|
<PackageReference Include="KrakenExchange.Net" Version="6.0.0" />
|
||||||
<PackageReference Include="Kucoin.Net" Version="6.0.0" />
|
<PackageReference Include="Kucoin.Net" Version="7.0.0" />
|
||||||
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
|
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
|
||||||
<PackageReference Include="WhiteBit.Net" Version="1.4.0" />
|
<PackageReference Include="WhiteBit.Net" Version="2.0.0" />
|
||||||
|
<PackageReference Include="XT.Net" Version="2.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
@inject IMexcRestClient mexcClient
|
@inject IMexcRestClient mexcClient
|
||||||
@inject IOKXRestClient okxClient
|
@inject IOKXRestClient okxClient
|
||||||
@inject IWhiteBitRestClient whitebitClient
|
@inject IWhiteBitRestClient whitebitClient
|
||||||
|
@inject IXTRestClient xtClient
|
||||||
|
|
||||||
<h3>BTC-USD prices:</h3>
|
<h3>BTC-USD prices:</h3>
|
||||||
@foreach(var price in _prices.OrderBy(p => p.Key))
|
@foreach(var price in _prices.OrderBy(p => p.Key))
|
||||||
@ -33,7 +34,7 @@
|
|||||||
var binanceTask = binanceClient.SpotApi.ExchangeData.GetTickerAsync("BTCUSDT");
|
var binanceTask = binanceClient.SpotApi.ExchangeData.GetTickerAsync("BTCUSDT");
|
||||||
var bingXTask = bingXClient.SpotApi.ExchangeData.GetTickersAsync("BTC-USDT");
|
var bingXTask = bingXClient.SpotApi.ExchangeData.GetTickersAsync("BTC-USDT");
|
||||||
var bitfinexTask = bitfinexClient.SpotApi.ExchangeData.GetTickerAsync("tBTCUSD");
|
var bitfinexTask = bitfinexClient.SpotApi.ExchangeData.GetTickerAsync("tBTCUSD");
|
||||||
var bitgetTask = bitgetClient.SpotApi.ExchangeData.GetTickerAsync("BTCUSDT_SPBL");
|
var bitgetTask = bitgetClient.SpotApiV2.ExchangeData.GetTickersAsync("BTCUSDT");
|
||||||
var bitmartTask = bitmartClient.SpotApi.ExchangeData.GetTickerAsync("BTC_USDT");
|
var bitmartTask = bitmartClient.SpotApi.ExchangeData.GetTickerAsync("BTC_USDT");
|
||||||
var bitmexTask = bitmexClient.ExchangeApi.ExchangeData.GetSymbolsAsync("XBT_USDT");
|
var bitmexTask = bitmexClient.ExchangeApi.ExchangeData.GetSymbolsAsync("XBT_USDT");
|
||||||
var bybitTask = bybitClient.V5Api.ExchangeData.GetSpotTickersAsync("BTCUSDT");
|
var bybitTask = bybitClient.V5Api.ExchangeData.GetSpotTickersAsync("BTCUSDT");
|
||||||
@ -49,6 +50,7 @@
|
|||||||
var mexcTask = mexcClient.SpotApi.ExchangeData.GetTickerAsync("BTCUSDT");
|
var mexcTask = mexcClient.SpotApi.ExchangeData.GetTickerAsync("BTCUSDT");
|
||||||
var okxTask = okxClient.UnifiedApi.ExchangeData.GetTickerAsync("BTCUSDT");
|
var okxTask = okxClient.UnifiedApi.ExchangeData.GetTickerAsync("BTCUSDT");
|
||||||
var whitebitTask = whitebitClient.V4Api.ExchangeData.GetTickersAsync();
|
var whitebitTask = whitebitClient.V4Api.ExchangeData.GetTickersAsync();
|
||||||
|
var xtTask = xtClient.SpotApi.ExchangeData.GetTickersAsync("eth_btc");
|
||||||
|
|
||||||
await Task.WhenAll(binanceTask, bingXTask, bitfinexTask, bitgetTask, bitmartTask, bybitTask, coinexTask, deepCoinTask, gateioTask, htxTask, krakenTask, kucoinTask, mexcTask, okxTask);
|
await Task.WhenAll(binanceTask, bingXTask, bitfinexTask, bitgetTask, bitmartTask, bybitTask, coinexTask, deepCoinTask, gateioTask, htxTask, krakenTask, kucoinTask, mexcTask, okxTask);
|
||||||
|
|
||||||
@ -62,10 +64,10 @@
|
|||||||
_prices.Add("Bitfinex", bitfinexTask.Result.Data.LastPrice);
|
_prices.Add("Bitfinex", bitfinexTask.Result.Data.LastPrice);
|
||||||
|
|
||||||
if (bitgetTask.Result.Success)
|
if (bitgetTask.Result.Success)
|
||||||
_prices.Add("Bitget", bitgetTask.Result.Data.ClosePrice);
|
_prices.Add("Bitget", bitgetTask.Result.Data.Single().LastPrice);
|
||||||
|
|
||||||
if (bitmartTask.Result.Success)
|
if (bitmartTask.Result.Success)
|
||||||
_prices.Add("BitMart", bitgetTask.Result.Data.ClosePrice);
|
_prices.Add("BitMart", bitmartTask.Result.Data.LastPrice);
|
||||||
|
|
||||||
if (bitmexTask.Result.Success)
|
if (bitmexTask.Result.Success)
|
||||||
_prices.Add("BitMEX", bitmexTask.Result.Data.First().LastPrice);
|
_prices.Add("BitMEX", bitmexTask.Result.Data.First().LastPrice);
|
||||||
@ -119,6 +121,9 @@
|
|||||||
var tickers = whitebitTask.Result.Data;
|
var tickers = whitebitTask.Result.Data;
|
||||||
_prices.Add("WhiteBit", tickers.Single(x => x.Symbol == "BTC_USDT").LastPrice);
|
_prices.Add("WhiteBit", tickers.Single(x => x.Symbol == "BTC_USDT").LastPrice);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (xtTask.Result.Success)
|
||||||
|
_prices.Add("XT", xtTask.Result.Data.Single().LastPrice ?? 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -18,10 +18,12 @@
|
|||||||
@inject IMexcSocketClient mexcSocketClient
|
@inject IMexcSocketClient mexcSocketClient
|
||||||
@inject IOKXSocketClient okxSocketClient
|
@inject IOKXSocketClient okxSocketClient
|
||||||
@inject IWhiteBitSocketClient whitebitSocketClient
|
@inject IWhiteBitSocketClient whitebitSocketClient
|
||||||
|
@inject IXTSocketClient xtSocketClient
|
||||||
@using System.Collections.Concurrent
|
@using System.Collections.Concurrent
|
||||||
@using CryptoExchange.Net.Objects
|
@using CryptoExchange.Net.Objects
|
||||||
@using CryptoExchange.Net.Objects.Sockets;
|
@using CryptoExchange.Net.Objects.Sockets;
|
||||||
@using CryptoExchange.Net.Sockets
|
@using CryptoExchange.Net.Sockets
|
||||||
|
@using XT.Net.Interfaces.Clients
|
||||||
@implements IDisposable
|
@implements IDisposable
|
||||||
|
|
||||||
<h3>ETH-BTC prices, live updates:</h3>
|
<h3>ETH-BTC prices, live updates:</h3>
|
||||||
@ -41,7 +43,7 @@
|
|||||||
binanceSocketClient.SpotApi.ExchangeData.SubscribeToTickerUpdatesAsync("ETHBTC", data => UpdateData("Binance", data.Data.LastPrice)),
|
binanceSocketClient.SpotApi.ExchangeData.SubscribeToTickerUpdatesAsync("ETHBTC", data => UpdateData("Binance", data.Data.LastPrice)),
|
||||||
bingXSocketClient.SpotApi.SubscribeToTickerUpdatesAsync("ETH-BTC", data => UpdateData("BingX", data.Data.LastPrice)),
|
bingXSocketClient.SpotApi.SubscribeToTickerUpdatesAsync("ETH-BTC", data => UpdateData("BingX", data.Data.LastPrice)),
|
||||||
bitfinexSocketClient.SpotApi.SubscribeToTickerUpdatesAsync("tETHBTC", data => UpdateData("Bitfinex", data.Data.LastPrice)),
|
bitfinexSocketClient.SpotApi.SubscribeToTickerUpdatesAsync("tETHBTC", data => UpdateData("Bitfinex", data.Data.LastPrice)),
|
||||||
bitgetSocketClient.SpotApi.SubscribeToTickerUpdatesAsync("ETHBTC", data => UpdateData("Bitget", data.Data.LastPrice)),
|
bitgetSocketClient.SpotApiV2.SubscribeToTickerUpdatesAsync("ETHBTC", data => UpdateData("Bitget", data.Data.LastPrice)),
|
||||||
bitmartSocketClient.SpotApi.SubscribeToTickerUpdatesAsync("ETH_BTC", data => UpdateData("BitMart", data.Data.LastPrice)),
|
bitmartSocketClient.SpotApi.SubscribeToTickerUpdatesAsync("ETH_BTC", data => UpdateData("BitMart", data.Data.LastPrice)),
|
||||||
bitmexSocketClient.ExchangeApi.SubscribeToSymbolUpdatesAsync("ETH_XBT", data => UpdateData("BitMEX", data.Data.LastPrice ?? 0)),
|
bitmexSocketClient.ExchangeApi.SubscribeToSymbolUpdatesAsync("ETH_XBT", data => UpdateData("BitMEX", data.Data.LastPrice ?? 0)),
|
||||||
bybitSocketClient.V5SpotApi.SubscribeToTickerUpdatesAsync("ETHBTC", data => UpdateData("Bybit", data.Data.LastPrice)),
|
bybitSocketClient.V5SpotApi.SubscribeToTickerUpdatesAsync("ETHBTC", data => UpdateData("Bybit", data.Data.LastPrice)),
|
||||||
@ -51,6 +53,7 @@
|
|||||||
deepCoinSocketClient.ExchangeApi.SubscribeToSymbolUpdatesAsync("ETH-BTC", data => UpdateData("DeepCoin", data.Data.LastPrice ?? 0)),
|
deepCoinSocketClient.ExchangeApi.SubscribeToSymbolUpdatesAsync("ETH-BTC", data => UpdateData("DeepCoin", data.Data.LastPrice ?? 0)),
|
||||||
gateioSocketClient.SpotApi.SubscribeToTickerUpdatesAsync("ETH_BTC", data => UpdateData("GateIo", data.Data.LastPrice)),
|
gateioSocketClient.SpotApi.SubscribeToTickerUpdatesAsync("ETH_BTC", data => UpdateData("GateIo", data.Data.LastPrice)),
|
||||||
htxSocketClient.SpotApi.SubscribeToTickerUpdatesAsync("ethbtc", data => UpdateData("HTX", data.Data.ClosePrice ?? 0)),
|
htxSocketClient.SpotApi.SubscribeToTickerUpdatesAsync("ethbtc", data => UpdateData("HTX", data.Data.ClosePrice ?? 0)),
|
||||||
|
xtSocketClient.SpotApi.SubscribeToTickerUpdatesAsync("eth_btc", data => UpdateData("XT", data.Data.LastPrice ?? 0)),
|
||||||
// HyperLiquid doesn't support the ETH/BTC pair
|
// HyperLiquid doesn't support the ETH/BTC pair
|
||||||
//hyperLiquidSocketClient.SpotApi.SubscribeToSymbolUpdatesAsync("ETH", data => UpdateData("HyperLiquid", data.Data.MidPrice ?? 0)),
|
//hyperLiquidSocketClient.SpotApi.SubscribeToSymbolUpdatesAsync("ETH", data => UpdateData("HyperLiquid", data.Data.MidPrice ?? 0)),
|
||||||
krakenSocketClient.SpotApi.SubscribeToTickerUpdatesAsync("ETH/BTC", data => UpdateData("Kraken", data.Data.LastPrice)),
|
krakenSocketClient.SpotApi.SubscribeToTickerUpdatesAsync("ETH/BTC", data => UpdateData("Kraken", data.Data.LastPrice)),
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
@using Bybit.Net.Interfaces
|
@using Bybit.Net.Interfaces
|
||||||
@using CoinEx.Net.Interfaces
|
@using CoinEx.Net.Interfaces
|
||||||
@using Coinbase.Net.Interfaces
|
@using Coinbase.Net.Interfaces
|
||||||
|
@using CryptoExchange.Net.Authentication
|
||||||
@using CryptoExchange.Net.Interfaces
|
@using CryptoExchange.Net.Interfaces
|
||||||
@using CryptoCom.Net.Interfaces
|
@using CryptoCom.Net.Interfaces
|
||||||
@using DeepCoin.Net.Interfaces
|
@using DeepCoin.Net.Interfaces
|
||||||
@ -22,6 +23,7 @@
|
|||||||
@using Mexc.Net.Interfaces
|
@using Mexc.Net.Interfaces
|
||||||
@using OKX.Net.Interfaces;
|
@using OKX.Net.Interfaces;
|
||||||
@using WhiteBit.Net.Interfaces
|
@using WhiteBit.Net.Interfaces
|
||||||
|
@using XT.Net.Interfaces
|
||||||
@inject IBinanceOrderBookFactory binanceFactory
|
@inject IBinanceOrderBookFactory binanceFactory
|
||||||
@inject IBingXOrderBookFactory bingXFactory
|
@inject IBingXOrderBookFactory bingXFactory
|
||||||
@inject IBitfinexOrderBookFactory bitfinexFactory
|
@inject IBitfinexOrderBookFactory bitfinexFactory
|
||||||
@ -41,6 +43,7 @@
|
|||||||
@inject IMexcOrderBookFactory mexcFactory
|
@inject IMexcOrderBookFactory mexcFactory
|
||||||
@inject IOKXOrderBookFactory okxFactory
|
@inject IOKXOrderBookFactory okxFactory
|
||||||
@inject IWhiteBitOrderBookFactory whitebitFactory
|
@inject IWhiteBitOrderBookFactory whitebitFactory
|
||||||
|
@inject IXTOrderBookFactory xtFactory
|
||||||
@implements IDisposable
|
@implements IDisposable
|
||||||
|
|
||||||
<h3>ETH-BTC books, live updates:</h3>
|
<h3>ETH-BTC books, live updates:</h3>
|
||||||
@ -69,7 +72,7 @@
|
|||||||
// Since the Kucoin order book stream needs authentication we will need to provide API credentials beforehand
|
// Since the Kucoin order book stream needs authentication we will need to provide API credentials beforehand
|
||||||
KucoinRestClient.SetDefaultOptions(options =>
|
KucoinRestClient.SetDefaultOptions(options =>
|
||||||
{
|
{
|
||||||
options.ApiCredentials = new Kucoin.Net.Objects.KucoinApiCredentials("KEY", "SECRET", "PASSPHRASE");
|
options.ApiCredentials = new ApiCredentials("KEY", "SECRET", "PASSPHRASE");
|
||||||
});
|
});
|
||||||
|
|
||||||
_books = new Dictionary<string, ISymbolOrderBook>
|
_books = new Dictionary<string, ISymbolOrderBook>
|
||||||
@ -85,7 +88,8 @@
|
|||||||
{ "CoinEx", coinExFactory.CreateSpot("ETHBTC") },
|
{ "CoinEx", coinExFactory.CreateSpot("ETHBTC") },
|
||||||
{ "CryptoCom", cryptocomFactory.Create("ETH_BTC") },
|
{ "CryptoCom", cryptocomFactory.Create("ETH_BTC") },
|
||||||
{ "GateIo", gateioFactory.CreateSpot("ETH_BTC") },
|
{ "GateIo", gateioFactory.CreateSpot("ETH_BTC") },
|
||||||
{ "DeepCoin", deepCoinFactory.Create("ETH-BTC") },
|
// DeepCoin does not support the ETH/BTC pair
|
||||||
|
//{ "DeepCoin", deepCoinFactory.Create("ETH-BTC") },
|
||||||
{ "HTX", htxFactory.CreateSpot("ethbtc") },
|
{ "HTX", htxFactory.CreateSpot("ethbtc") },
|
||||||
// HyperLiquid does not support the ETH/BTC pair
|
// HyperLiquid does not support the ETH/BTC pair
|
||||||
//{ "HyperLiquid", hyperLiquidFactory.Create("ETH/BTC") },
|
//{ "HyperLiquid", hyperLiquidFactory.Create("ETH/BTC") },
|
||||||
@ -94,9 +98,10 @@
|
|||||||
{ "Mexc", mexcFactory.CreateSpot("ETHBTC") },
|
{ "Mexc", mexcFactory.CreateSpot("ETHBTC") },
|
||||||
{ "OKX", okxFactory.Create("ETH-BTC") },
|
{ "OKX", okxFactory.Create("ETH-BTC") },
|
||||||
{ "WhiteBit", whitebitFactory.CreateV4("ETH_BTC") },
|
{ "WhiteBit", whitebitFactory.CreateV4("ETH_BTC") },
|
||||||
|
{ "XT", xtFactory.CreateSpot("eth_btc") },
|
||||||
};
|
};
|
||||||
|
|
||||||
await Task.WhenAll(_books.Select(b => b.Value.StartAsync()));
|
var result = await Task.WhenAll(_books.Select(b => b.Value.StartAsync()));
|
||||||
|
|
||||||
// Use a manual update timer so the page isn't refreshed too often
|
// Use a manual update timer so the page isn't refreshed too often
|
||||||
_timer = new Timer(500);
|
_timer = new Timer(500);
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
@using Mexc.Net.Interfaces
|
@using Mexc.Net.Interfaces
|
||||||
@using OKX.Net.Interfaces;
|
@using OKX.Net.Interfaces;
|
||||||
@using WhiteBit.Net.Interfaces
|
@using WhiteBit.Net.Interfaces
|
||||||
|
@using XT.Net.Interfaces
|
||||||
@inject IBinanceTrackerFactory binanceFactory
|
@inject IBinanceTrackerFactory binanceFactory
|
||||||
@inject IBingXTrackerFactory bingXFactory
|
@inject IBingXTrackerFactory bingXFactory
|
||||||
@inject IBitfinexTrackerFactory bitfinexFactory
|
@inject IBitfinexTrackerFactory bitfinexFactory
|
||||||
@ -43,6 +44,7 @@
|
|||||||
@inject IMexcTrackerFactory mexcFactory
|
@inject IMexcTrackerFactory mexcFactory
|
||||||
@inject IOKXTrackerFactory okxFactory
|
@inject IOKXTrackerFactory okxFactory
|
||||||
@inject IWhiteBitTrackerFactory whitebitFactory
|
@inject IWhiteBitTrackerFactory whitebitFactory
|
||||||
|
@inject IXTTrackerFactory xtFactory
|
||||||
@implements IDisposable
|
@implements IDisposable
|
||||||
|
|
||||||
<h3>ETH-BTC trade Trackers, live updates:</h3>
|
<h3>ETH-BTC trade Trackers, live updates:</h3>
|
||||||
@ -89,6 +91,7 @@
|
|||||||
{ mexcFactory.CreateTradeTracker(usdtSymbol, period: TimeSpan.FromMinutes(5)) },
|
{ mexcFactory.CreateTradeTracker(usdtSymbol, period: TimeSpan.FromMinutes(5)) },
|
||||||
{ okxFactory.CreateTradeTracker(usdtSymbol, period: TimeSpan.FromMinutes(5)) },
|
{ okxFactory.CreateTradeTracker(usdtSymbol, period: TimeSpan.FromMinutes(5)) },
|
||||||
{ whitebitFactory.CreateTradeTracker(usdtSymbol, period: TimeSpan.FromMinutes(5)) },
|
{ whitebitFactory.CreateTradeTracker(usdtSymbol, period: TimeSpan.FromMinutes(5)) },
|
||||||
|
{ xtFactory.CreateTradeTracker(usdtSymbol, period: TimeSpan.FromMinutes(5)) },
|
||||||
};
|
};
|
||||||
|
|
||||||
await Task.WhenAll(_trackers.Select(b => b.StartAsync()));
|
await Task.WhenAll(_trackers.Select(b => b.StartAsync()));
|
||||||
|
@ -31,9 +31,6 @@ namespace BlazorClient
|
|||||||
services.AddBinance(restOptions =>
|
services.AddBinance(restOptions =>
|
||||||
{
|
{
|
||||||
restOptions.ApiCredentials = new ApiCredentials("KEY", "SECRET");
|
restOptions.ApiCredentials = new ApiCredentials("KEY", "SECRET");
|
||||||
}, socketOptions =>
|
|
||||||
{
|
|
||||||
socketOptions.ApiCredentials = new ApiCredentials("KEY", "SECRET");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
services.AddBingX();
|
services.AddBingX();
|
||||||
@ -54,6 +51,7 @@ namespace BlazorClient
|
|||||||
services.AddMexc();
|
services.AddMexc();
|
||||||
services.AddOKX();
|
services.AddOKX();
|
||||||
services.AddWhiteBit();
|
services.AddWhiteBit();
|
||||||
|
services.AddXT();
|
||||||
}
|
}
|
||||||
|
|
||||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||||
|
@ -27,4 +27,5 @@
|
|||||||
@using Mexc.Net.Interfaces.Clients;
|
@using Mexc.Net.Interfaces.Clients;
|
||||||
@using OKX.Net.Interfaces.Clients;
|
@using OKX.Net.Interfaces.Clients;
|
||||||
@using WhiteBit.Net.Interfaces.Clients
|
@using WhiteBit.Net.Interfaces.Clients
|
||||||
|
@using XT.Net.Interfaces.Clients
|
||||||
@using CryptoExchange.Net.Interfaces;
|
@using CryptoExchange.Net.Interfaces;
|
@ -6,20 +6,20 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Binance.Net" Version="10.9.0" />
|
<PackageReference Include="Binance.Net" Version="11.0.0" />
|
||||||
<PackageReference Include="Bitfinex.Net" Version="7.10.0" />
|
<PackageReference Include="Bitfinex.Net" Version="9.0.0" />
|
||||||
<PackageReference Include="BitMart.Net" Version="1.7.0" />
|
<PackageReference Include="BitMart.Net" Version="2.0.0" />
|
||||||
<PackageReference Include="Bybit.Net" Version="3.16.0" />
|
<PackageReference Include="Bybit.Net" Version="5.0.0" />
|
||||||
<PackageReference Include="CoinEx.Net" Version="7.9.0" />
|
<PackageReference Include="CoinEx.Net" Version="9.0.0" />
|
||||||
<PackageReference Include="CryptoCom.Net" Version="1.2.0" />
|
<PackageReference Include="CryptoCom.Net" Version="2.0.0" />
|
||||||
<PackageReference Include="GateIo.Net" Version="1.12.0" />
|
<PackageReference Include="GateIo.Net" Version="2.0.0" />
|
||||||
<PackageReference Include="JK.Bitget.Net" Version="1.13.0" />
|
<PackageReference Include="JK.Bitget.Net" Version="2.0.0" />
|
||||||
<PackageReference Include="JK.Mexc.Net" Version="1.11.0" />
|
<PackageReference Include="JK.Mexc.Net" Version="3.0.0" />
|
||||||
<PackageReference Include="JK.OKX.Net" Version="2.8.0" />
|
<PackageReference Include="JK.OKX.Net" Version="3.0.0" />
|
||||||
<PackageReference Include="JKorf.Coinbase.Net" Version="1.4.0" />
|
<PackageReference Include="JKorf.Coinbase.Net" Version="2.0.0" />
|
||||||
<PackageReference Include="JKorf.HTX.Net" Version="6.4.0" />
|
<PackageReference Include="JKorf.HTX.Net" Version="7.0.0" />
|
||||||
<PackageReference Include="KrakenExchange.Net" Version="5.2.0" />
|
<PackageReference Include="KrakenExchange.Net" Version="6.0.0" />
|
||||||
<PackageReference Include="Kucoin.Net" Version="5.18.0" />
|
<PackageReference Include="Kucoin.Net" Version="7.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -8,9 +8,9 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Binance.Net" Version="10.9.0" />
|
<PackageReference Include="Binance.Net" Version="11.0.0" />
|
||||||
<PackageReference Include="BitMart.Net" Version="1.7.0" />
|
<PackageReference Include="BitMart.Net" Version="2.0.0" />
|
||||||
<PackageReference Include="JK.OKX.Net" Version="2.8.0" />
|
<PackageReference Include="JK.OKX.Net" Version="3.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
81
README.md
81
README.md
@ -5,34 +5,34 @@
|
|||||||
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.
|
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.
|
||||||
Note that the CryptoExchange.Net package itself can not be used directly for accessing API's. Either install a client library from the list below or use [CryptoClients.Net](https://github.com/jkorf/CryptoClients.Net) which includes access to all exchange API's.
|
Note that the CryptoExchange.Net package itself can not be used directly for accessing API's. Either install a client library from the list below or use [CryptoClients.Net](https://github.com/jkorf/CryptoClients.Net) which includes access to all exchange API's.
|
||||||
|
|
||||||
For more information on what CryptoExchange.Net and it's client libraries offers see the [Documentation](https://jkorf.github.io/CryptoExchange.Net/).
|
For more information on what CryptoExchange.Net and it's client libraries offers see the [Documentation](https://cryptoexchange.jkorf.dev/).
|
||||||
|
|
||||||
### Current implementations
|
### CryptoExchange.Net Ecosystem
|
||||||
The following API's are directly supported. Note that there are 3rd party implementations going around, but only these are created and supported by me:
|
Full list of all libraries part of the CryptoExchange.Net ecosystem. Consider using a referral link to support development, as well as potentially get some trading fee discount!
|
||||||
|
|
||||||
|Exchange|Repository|Nuget|
|
||Exchange|Type|Repository|Nuget|Referral Link|Referral Fee Discount|
|
||||||
|--|--|--|
|
|--|--|--|--|--|--|--|
|
||||||
|Binance|[JKorf/Binance.Net](https://github.com/JKorf/Binance.Net)|[](https://www.nuget.org/packages/Binance.Net)|
|
||Binance|CEX|[JKorf/Binance.Net](https://github.com/JKorf/Binance.Net)|[](https://www.nuget.org/packages/Binance.Net)|[Link](https://accounts.binance.com/register?ref=X5K3F2ZG)|20%|
|
||||||
|BingX|[JKorf/BingX.Net](https://github.com/JKorf/BingX.Net)|[](https://www.nuget.org/packages/JK.BingX.Net)|
|
||BingX|CEX|[JKorf/BingX.Net](https://github.com/JKorf/BingX.Net)|[](https://www.nuget.org/packages/JK.BingX.Net)|[Link](https://bingx.com/invite/FFHRJKWG/)|20%|
|
||||||
|Bitfinex|[JKorf/Bitfinex.Net](https://github.com/JKorf/Bitfinex.Net)|[](https://www.nuget.org/packages/Bitfinex.Net)|
|
||Bitfinex|CEX|[JKorf/Bitfinex.Net](https://github.com/JKorf/Bitfinex.Net)|[](https://www.nuget.org/packages/Bitfinex.Net)|-|-|
|
||||||
|Bitget|[JKorf/Bitget.Net](https://github.com/JKorf/Bitget.Net)|[](https://www.nuget.org/packages/JK.Bitget.Net)|
|
||Bitget|CEX|[JKorf/Bitget.Net](https://github.com/JKorf/Bitget.Net)|[](https://www.nuget.org/packages/JK.Bitget.Net)|[Link](https://partner.bitget.com/bg/1qlf6pj1)|20%|
|
||||||
|BitMart|[JKorf/BitMart.Net](https://github.com/JKorf/BitMart.Net)|[](https://www.nuget.org/packages/BitMart.Net)|
|
||BitMart|CEX|[JKorf/BitMart.Net](https://github.com/JKorf/BitMart.Net)|[](https://www.nuget.org/packages/BitMart.Net)|[Link](https://www.bitmart.com/invite/JKorfAPI/en-US)|30%|
|
||||||
|BitMEX|[JKorf/BitMEX.Net](https://github.com/JKorf/BitMEX.Net)|[](https://www.nuget.org/packages/JKorf.BitMEX.Net)|
|
||BitMEX|CEX|[JKorf/BitMEX.Net](https://github.com/JKorf/BitMEX.Net)|[](https://www.nuget.org/packages/JKorf.BitMEX.Net)|[Link](https://www.bitmex.com/app/register/94f98e)|30%|
|
||||||
|Bybit|[JKorf/Bybit.Net](https://github.com/JKorf/Bybit.Net)|[](https://www.nuget.org/packages/Bybit.Net)|
|
||Bybit|CEX|[JKorf/Bybit.Net](https://github.com/JKorf/Bybit.Net)|[](https://www.nuget.org/packages/Bybit.Net)|[Link](https://partner.bybit.com/b/jkorf)|-|
|
||||||
|Coinbase|[JKorf/Coinbase.Net](https://github.com/JKorf/Coinbase.Net)|[](https://www.nuget.org/packages/JKorf.Coinbase.Net)|
|
||Coinbase|CEX|[JKorf/Coinbase.Net](https://github.com/JKorf/Coinbase.Net)|[](https://www.nuget.org/packages/JKorf.Coinbase.Net)|[Link](https://advanced.coinbase.com/join/T6H54H8)|-|
|
||||||
|CoinEx|[JKorf/CoinEx.Net](https://github.com/JKorf/CoinEx.Net)|[](https://www.nuget.org/packages/CoinEx.Net)|
|
||CoinEx|CEX|[JKorf/CoinEx.Net](https://github.com/JKorf/CoinEx.Net)|[](https://www.nuget.org/packages/CoinEx.Net)|[Link](https://www.coinex.com/register?rc=rbtnp)|20%|
|
||||||
|CoinGecko|[JKorf/CoinGecko.Net](https://github.com/JKorf/CoinGecko.Net)|[](https://www.nuget.org/packages/CoinGecko.Net)|
|
||CoinGecko|-|[JKorf/CoinGecko.Net](https://github.com/JKorf/CoinGecko.Net)|[](https://www.nuget.org/packages/CoinGecko.Net)|-|-|
|
||||||
|Crypto.com|[JKorf/CryptoCom.Net](https://github.com/JKorf/CryptoCom.Net)|[](https://www.nuget.org/packages/CryptoCom.Net)|
|
||Crypto.com|CEX|[JKorf/CryptoCom.Net](https://github.com/JKorf/CryptoCom.Net)|[](https://www.nuget.org/packages/CryptoCom.Net)|[Link](https://crypto.com/exch/26ge92xbkn)|-|
|
||||||
|DeepCoin|[JKorf/DeepCoin.Net](https://github.com/JKorf/DeepCoin.Net)|[](https://www.nuget.org/packages/DeepCoin.Net)|
|
||DeepCoin|CEX|[JKorf/DeepCoin.Net](https://github.com/JKorf/DeepCoin.Net)|[](https://www.nuget.org/packages/DeepCoin.Net)|[Link](https://s.deepcoin.com/jddhfca)|-|
|
||||||
|Gate.io|[JKorf/GateIo.Net](https://github.com/JKorf/GateIo.Net)|[](https://www.nuget.org/packages/GateIo.Net)|
|
||Gate.io|CEX|[JKorf/GateIo.Net](https://github.com/JKorf/GateIo.Net)|[](https://www.nuget.org/packages/GateIo.Net)|[Link](https://www.gate.io/share/JKorf)|20%|
|
||||||
|HTX|[JKorf/HTX.Net](https://github.com/JKorf/HTX.Net)|[](https://www.nuget.org/packages/JKorf.HTX.Net)|
|
||HTX|CEX|[JKorf/HTX.Net](https://github.com/JKorf/HTX.Net)|[](https://www.nuget.org/packages/JKorf.HTX.Net)|[Link](https://www.htx.com/invite/en-us/1f?invite_code=ekek5223)|30%|
|
||||||
|HyperLiquid|[JKorf/HyperLiquid.Net](https://github.com/JKorf/HyperLiquid.Net)|[](https://www.nuget.org/packages/HyperLiquid.Net)|
|
||HyperLiquid|DEX|[JKorf/HyperLiquid.Net](https://github.com/JKorf/HyperLiquid.Net)|[](https://www.nuget.org/packages/HyperLiquid.Net)|[Link](https://app.hyperliquid.xyz/join/JKORF)|4%|
|
||||||
|Kraken|[JKorf/Kraken.Net](https://github.com/JKorf/Kraken.Net)|[](https://www.nuget.org/packages/KrakenExchange.Net)|
|
||Kraken|CEX|[JKorf/Kraken.Net](https://github.com/JKorf/Kraken.Net)|[](https://www.nuget.org/packages/KrakenExchange.Net)|-|-|
|
||||||
|Kucoin|[JKorf/Kucoin.Net](https://github.com/JKorf/Kucoin.Net)|[](https://www.nuget.org/packages/Kucoin.Net)|
|
||Kucoin|CEX|[JKorf/Kucoin.Net](https://github.com/JKorf/Kucoin.Net)|[](https://www.nuget.org/packages/Kucoin.Net)|[Link](https://www.kucoin.com/r/rf/QBS4FPED)|-|
|
||||||
|Mexc|[JKorf/Mexc.Net](https://github.com/JKorf/Mexc.Net)|[](https://www.nuget.org/packages/JK.Mexc.Net)|
|
||Mexc|CEX|[JKorf/Mexc.Net](https://github.com/JKorf/Mexc.Net)|[](https://www.nuget.org/packages/JK.Mexc.Net)|-|-|
|
||||||
|OKX|[JKorf/OKX.Net](https://github.com/JKorf/OKX.Net)|[](https://www.nuget.org/packages/JK.OKX.Net)|
|
||OKX|CEX|[JKorf/OKX.Net](https://github.com/JKorf/OKX.Net)|[](https://www.nuget.org/packages/JK.OKX.Net)|[Link](https://www.okx.com/join/14592495)|20%|
|
||||||
|WhiteBit|[JKorf/WhiteBit.Net](https://github.com/JKorf/WhiteBit.Net)|[](https://www.nuget.org/packages/WhiteBit.Net)|
|
||WhiteBit|CEX|[JKorf/WhiteBit.Net](https://github.com/JKorf/WhiteBit.Net)|[](https://www.nuget.org/packages/WhiteBit.Net)|[Link](https://whitebit.com/referral/a8e59b59-186c-4662-824c-3095248e0edf)|-|
|
||||||
|XT|[JKorf/XT.Net](https://github.com/JKorf/XT.Net)|[](https://www.nuget.org/packages/XT.Net)|
|
||XT|CEX|[JKorf/XT.Net](https://github.com/JKorf/XT.Net)|[](https://www.nuget.org/packages/XT.Net)|[Link](https://www.xt.com/ru/accounts/register?ref=CZG39C)|25%|
|
||||||
|
|
||||||
Any of these can be installed independently or install [CryptoClients.Net](https://github.com/jkorf/CryptoClients.Net) which includes all exchange API's.
|
Any of these can be installed independently or install [CryptoClients.Net](https://github.com/jkorf/CryptoClients.Net) which includes all exchange API's.
|
||||||
|
|
||||||
@ -43,22 +43,8 @@ A Discord server is available [here](https://discord.gg/MSpeEtSY8t). Feel free t
|
|||||||
## Support the project
|
## Support the project
|
||||||
Any support is greatly appreciated.
|
Any support is greatly appreciated.
|
||||||
|
|
||||||
## Referral
|
### Referral
|
||||||
When creating an account on new exchanges please consider using a referral link from below to support development
|
When creating an account on new exchanges please consider using a referral link from above.
|
||||||
|
|
||||||
|Exchange|Link|
|
|
||||||
|--|--|
|
|
||||||
|Bybit|[https://partner.bybit.com/b/jkorf](https://partner.bybit.com/b/jkorf)|
|
|
||||||
|Coinbase|[https://advanced.coinbase.com/join/T6H54H8](https://advanced.coinbase.com/join/T6H54H8)|
|
|
||||||
|CoinEx|[https://www.coinex.com/register?refer_code=hd6gn](https://www.coinex.com/register?refer_code=hd6gn)|
|
|
||||||
|Crypto.com|[https://crypto.com/exch/26ge92xbkn](https://crypto.com/exch/26ge92xbkn)|
|
|
||||||
|DeepCoin|[https://s.deepcoin.com/jddhfca)|
|
|
||||||
|HTX|[https://www.htx.com/invite/en-us/1f?invite_code=fxp9](https://www.htx.com/invite/en-us/1f?invite_code=fxp9)|
|
|
||||||
|HyperLiquid|[https://app.hyperliquid.xyz/join/JKORF](https://app.hyperliquid.xyz/join/JKORF)|
|
|
||||||
|Kucoin|[https://www.kucoin.com/r/rf/QBS4FPED](https://www.kucoin.com/r/rf/QBS4FPED)|
|
|
||||||
|OKX|[https://okx.com/join/48046699](https://okx.com/join/48046699)|
|
|
||||||
|WhiteBit|[https://whitebit.com/referral/a8e59b59-186c-4662-824c-3095248e0edf](https://whitebit.com/referral/a8e59b59-186c-4662-824c-3095248e0edf)|
|
|
||||||
|XT|[https://www.xt.com/en/accounts/register?ref=1HRM5J](https://www.xt.com/en/accounts/register?ref=1HRM5J)|
|
|
||||||
|
|
||||||
### Donate
|
### Donate
|
||||||
Make a one time donation in a crypto currency of your choice. If you prefer to donate a currency not listed here please contact me.
|
Make a one time donation in a crypto currency of your choice. If you prefer to donate a currency not listed here please contact me.
|
||||||
@ -71,6 +57,17 @@ 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).
|
Alternatively, sponsor me on Github using [Github Sponsors](https://github.com/sponsors/JKorf).
|
||||||
|
|
||||||
## Release notes
|
## Release notes
|
||||||
|
* Version 9.1.0 - 28 May 2025
|
||||||
|
* Added JsonConverter implementation for SharedQuantity and SharedSymbol types, making usage of the types easier
|
||||||
|
* Updated dotnet dependency packages from 9.0.0 to 9.0.5
|
||||||
|
* Replaced Microsoft.Extensions.Logging.Abstractions with Microsoft.Extensions.Logging
|
||||||
|
* Replaced Microsoft.Extensions.Options.ConfigurationExtensions with Microsoft.Extensions.Configuration.Binder, which includes a source generator for AOT publishing
|
||||||
|
* Removed redundant Microsoft.Extensions.DependencyInjection.Abstractions package reference
|
||||||
|
|
||||||
|
* Version 9.0.1 - 20 May 2025
|
||||||
|
* Improved response time on CancellationToken cancel during subscribing
|
||||||
|
* Added support for sending query without expecting a response
|
||||||
|
|
||||||
* Version 9.0.0 - 13 May 2025
|
* Version 9.0.0 - 13 May 2025
|
||||||
* Added support for Native AOT compilation
|
* Added support for Native AOT compilation
|
||||||
* Updated all IEnumerable response types to array response types
|
* Updated all IEnumerable response types to array response types
|
||||||
|
Loading…
x
Reference in New Issue
Block a user