mirror of
https://github.com/JKorf/CryptoExchange.Net
synced 2025-10-27 16:37:24 +00:00
Compare commits
13 Commits
CryptoExch
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dd60067684 | ||
|
|
04e4ddf525 | ||
|
|
99bf6d7c75 | ||
|
|
99a203933c | ||
|
|
b43d2a2040 | ||
|
|
ba9c406def | ||
|
|
f5f4d50cc9 | ||
|
|
f87506b490 | ||
|
|
f6f9a53ce5 | ||
|
|
61130ef54e | ||
|
|
e8bcbd59be | ||
|
|
d433ff7475 | ||
|
|
71957037d0 |
@ -6,9 +6,9 @@
|
|||||||
<PackageId>CryptoExchange.Net.Protobuf</PackageId>
|
<PackageId>CryptoExchange.Net.Protobuf</PackageId>
|
||||||
<Authors>JKorf</Authors>
|
<Authors>JKorf</Authors>
|
||||||
<Description>Protobuf support for CryptoExchange.Net</Description>
|
<Description>Protobuf support for CryptoExchange.Net</Description>
|
||||||
<PackageVersion>9.8.0</PackageVersion>
|
<PackageVersion>9.10.0</PackageVersion>
|
||||||
<AssemblyVersion>9.8.0</AssemblyVersion>
|
<AssemblyVersion>9.10.0</AssemblyVersion>
|
||||||
<FileVersion>9.8.0</FileVersion>
|
<FileVersion>9.10.0</FileVersion>
|
||||||
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
|
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
|
||||||
<PackageTags>CryptoExchange;CryptoExchange.Net</PackageTags>
|
<PackageTags>CryptoExchange;CryptoExchange.Net</PackageTags>
|
||||||
<RepositoryType>git</RepositoryType>
|
<RepositoryType>git</RepositoryType>
|
||||||
@ -41,7 +41,7 @@
|
|||||||
<DocumentationFile>CryptoExchange.Net.Protobuf.xml</DocumentationFile>
|
<DocumentationFile>CryptoExchange.Net.Protobuf.xml</DocumentationFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="CryptoExchange.Net" Version="9.8.0" />
|
<PackageReference Include="CryptoExchange.Net" Version="9.10.0" />
|
||||||
<PackageReference Include="protobuf-net" Version="3.2.56" />
|
<PackageReference Include="protobuf-net" Version="3.2.56" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
@ -5,6 +5,12 @@
|
|||||||
Protobuf support for CryptoExchange.Net.
|
Protobuf support for CryptoExchange.Net.
|
||||||
|
|
||||||
## Release notes
|
## Release notes
|
||||||
|
* Version 9.10.0 - 15 Oct 2025
|
||||||
|
* Updated CryptoExchange.Net version to 9.10.0, see https://github.com/JKorf/CryptoExchange.Net/releases/
|
||||||
|
|
||||||
|
* Version 9.9.0 - 06 Oct 2025
|
||||||
|
* Updated CryptoExchange.Net version to 9.9.0, see https://github.com/JKorf/CryptoExchange.Net/releases/
|
||||||
|
|
||||||
* Version 9.8.0 - 30 Sep 2025
|
* Version 9.8.0 - 30 Sep 2025
|
||||||
* Updated CryptoExchange.Net version to 9.8.0, see https://github.com/JKorf/CryptoExchange.Net/releases/
|
* Updated CryptoExchange.Net version to 9.8.0, see https://github.com/JKorf/CryptoExchange.Net/releases/
|
||||||
|
|
||||||
|
|||||||
@ -6,10 +6,10 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1"></PackageReference>
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.0"></PackageReference>
|
||||||
<PackageReference Include="Moq" Version="4.20.72" />
|
<PackageReference Include="Moq" Version="4.20.72" />
|
||||||
<PackageReference Include="NUnit" Version="4.3.2"></PackageReference>
|
<PackageReference Include="NUnit" Version="4.4.0"></PackageReference>
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="5.0.0"></PackageReference>
|
<PackageReference Include="NUnit3TestAdapter" Version="5.2.0"></PackageReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@ -14,8 +14,8 @@ namespace CryptoExchange.Net.Converters.SystemTextJson
|
|||||||
{
|
{
|
||||||
private static readonly DateTime _epoch = new(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
|
private static readonly DateTime _epoch = new(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
|
||||||
private const long _ticksPerSecond = TimeSpan.TicksPerMillisecond * 1000;
|
private const long _ticksPerSecond = TimeSpan.TicksPerMillisecond * 1000;
|
||||||
private const double _ticksPerMicrosecond = TimeSpan.TicksPerMillisecond / 1000d;
|
private const decimal _ticksPerMicrosecond = TimeSpan.TicksPerMillisecond / 1000m;
|
||||||
private const double _ticksPerNanosecond = TimeSpan.TicksPerMillisecond / 1000d / 1000;
|
private const decimal _ticksPerNanosecond = TimeSpan.TicksPerMillisecond / 1000m / 1000;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override bool CanConvert(Type typeToConvert)
|
public override bool CanConvert(Type typeToConvert)
|
||||||
@ -45,11 +45,11 @@ namespace CryptoExchange.Net.Converters.SystemTextJson
|
|||||||
|
|
||||||
if (reader.TokenType is JsonTokenType.Number)
|
if (reader.TokenType is JsonTokenType.Number)
|
||||||
{
|
{
|
||||||
var longValue = reader.GetDouble();
|
var decValue = reader.GetDecimal();
|
||||||
if (longValue == 0 || longValue < 0)
|
if (decValue == 0 || decValue < 0)
|
||||||
return default;
|
return default;
|
||||||
|
|
||||||
return ParseFromDouble(longValue);
|
return ParseFromDecimal(decValue);
|
||||||
}
|
}
|
||||||
else if (reader.TokenType is JsonTokenType.String)
|
else if (reader.TokenType is JsonTokenType.String)
|
||||||
{
|
{
|
||||||
@ -57,7 +57,7 @@ namespace CryptoExchange.Net.Converters.SystemTextJson
|
|||||||
if (string.IsNullOrWhiteSpace(stringValue)
|
if (string.IsNullOrWhiteSpace(stringValue)
|
||||||
|| stringValue == "-1"
|
|| stringValue == "-1"
|
||||||
|| stringValue == "0001-01-01T00:00:00Z"
|
|| stringValue == "0001-01-01T00:00:00Z"
|
||||||
|| double.TryParse(stringValue, out var doubleVal) && doubleVal == 0)
|
|| decimal.TryParse(stringValue, out var decVal) && decVal == 0)
|
||||||
{
|
{
|
||||||
return default;
|
return default;
|
||||||
}
|
}
|
||||||
@ -88,20 +88,24 @@ namespace CryptoExchange.Net.Converters.SystemTextJson
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Parse a long value to datetime
|
/// Parse a double value to datetime
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="longValue"></param>
|
public static DateTime ParseFromDouble(double value)
|
||||||
/// <returns></returns>
|
=> ParseFromDecimal((decimal)value);
|
||||||
public static DateTime ParseFromDouble(double longValue)
|
|
||||||
{
|
|
||||||
if (longValue < 19999999999)
|
|
||||||
return ConvertFromSeconds(longValue);
|
|
||||||
if (longValue < 19999999999999)
|
|
||||||
return ConvertFromMilliseconds(longValue);
|
|
||||||
if (longValue < 19999999999999999)
|
|
||||||
return ConvertFromMicroseconds(longValue);
|
|
||||||
|
|
||||||
return ConvertFromNanoseconds(longValue);
|
/// <summary>
|
||||||
|
/// Parse a decimal value to datetime
|
||||||
|
/// </summary>
|
||||||
|
public static DateTime ParseFromDecimal(decimal value)
|
||||||
|
{
|
||||||
|
if (value < 19999999999)
|
||||||
|
return ConvertFromSeconds(value);
|
||||||
|
if (value < 19999999999999)
|
||||||
|
return ConvertFromMilliseconds(value);
|
||||||
|
if (value < 19999999999999999)
|
||||||
|
return ConvertFromMicroseconds(value);
|
||||||
|
|
||||||
|
return ConvertFromNanoseconds(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -152,19 +156,19 @@ namespace CryptoExchange.Net.Converters.SystemTextJson
|
|||||||
return new DateTime(year + 2000, month, day, 0, 0, 0, DateTimeKind.Utc);
|
return new DateTime(year + 2000, month, day, 0, 0, 0, DateTimeKind.Utc);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (double.TryParse(stringValue, NumberStyles.Float, CultureInfo.InvariantCulture, out var doubleValue))
|
if (decimal.TryParse(stringValue, NumberStyles.Float, CultureInfo.InvariantCulture, out var decimalValue))
|
||||||
{
|
{
|
||||||
// Parse 1637745563.000 format
|
// Parse 1637745563.000 format
|
||||||
if (doubleValue <= 0)
|
if (decimalValue <= 0)
|
||||||
return default;
|
return default;
|
||||||
if (doubleValue < 19999999999)
|
if (decimalValue < 19999999999)
|
||||||
return ConvertFromSeconds(doubleValue);
|
return ConvertFromSeconds(decimalValue);
|
||||||
if (doubleValue < 19999999999999)
|
if (decimalValue < 19999999999999)
|
||||||
return ConvertFromMilliseconds((long)doubleValue);
|
return ConvertFromMilliseconds(decimalValue);
|
||||||
if (doubleValue < 19999999999999999)
|
if (decimalValue < 19999999999999999)
|
||||||
return ConvertFromMicroseconds((long)doubleValue);
|
return ConvertFromMicroseconds(decimalValue);
|
||||||
|
|
||||||
return ConvertFromNanoseconds((long)doubleValue);
|
return ConvertFromNanoseconds(decimalValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stringValue.Length == 10)
|
if (stringValue.Length == 10)
|
||||||
@ -188,54 +192,70 @@ namespace CryptoExchange.Net.Converters.SystemTextJson
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Convert a seconds since epoch (01-01-1970) value to DateTime
|
/// Convert a seconds since epoch (01-01-1970) value to DateTime
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="seconds"></param>
|
public static DateTime ConvertFromSeconds(decimal seconds) => _epoch.AddTicks((long)Math.Round(seconds * _ticksPerSecond));
|
||||||
/// <returns></returns>
|
|
||||||
public static DateTime ConvertFromSeconds(double seconds) => _epoch.AddTicks((long)Math.Round(seconds * _ticksPerSecond));
|
|
||||||
/// <summary>
|
|
||||||
/// Convert a milliseconds since epoch (01-01-1970) value to DateTime
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="milliseconds"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static DateTime ConvertFromMilliseconds(double milliseconds) => _epoch.AddTicks((long)Math.Round(milliseconds * TimeSpan.TicksPerMillisecond));
|
|
||||||
/// <summary>
|
|
||||||
/// Convert a microseconds since epoch (01-01-1970) value to DateTime
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="microseconds"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static DateTime ConvertFromMicroseconds(double microseconds) => _epoch.AddTicks((long)Math.Round(microseconds * _ticksPerMicrosecond));
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Convert a nanoseconds since epoch (01-01-1970) value to DateTime
|
/// Convert a nanoseconds since epoch (01-01-1970) value to DateTime
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="nanoseconds"></param>
|
public static DateTime ConvertFromSeconds(double seconds) => ConvertFromSeconds((decimal)seconds);
|
||||||
/// <returns></returns>
|
/// <summary>
|
||||||
public static DateTime ConvertFromNanoseconds(double nanoseconds) => _epoch.AddTicks((long)Math.Round(nanoseconds * _ticksPerNanosecond));
|
/// Convert a nanoseconds since epoch (01-01-1970) value to DateTime
|
||||||
|
/// </summary>
|
||||||
|
public static DateTime ConvertFromSeconds(long seconds) => ConvertFromSeconds((decimal)seconds);
|
||||||
|
/// <summary>
|
||||||
|
/// Convert a milliseconds since epoch (01-01-1970) value to DateTime
|
||||||
|
/// </summary>
|
||||||
|
public static DateTime ConvertFromMilliseconds(decimal milliseconds) => _epoch.AddTicks((long)Math.Round(milliseconds * TimeSpan.TicksPerMillisecond));
|
||||||
|
/// <summary>
|
||||||
|
/// Convert a nanoseconds since epoch (01-01-1970) value to DateTime
|
||||||
|
/// </summary>
|
||||||
|
public static DateTime ConvertFromMilliseconds(double milliseconds) => ConvertFromMilliseconds((decimal)milliseconds);
|
||||||
|
/// <summary>
|
||||||
|
/// Convert a nanoseconds since epoch (01-01-1970) value to DateTime
|
||||||
|
/// </summary>
|
||||||
|
public static DateTime ConvertFromMilliseconds(long milliseconds) => ConvertFromMilliseconds((decimal)milliseconds);
|
||||||
|
/// <summary>
|
||||||
|
/// Convert a microseconds since epoch (01-01-1970) value to DateTime
|
||||||
|
/// </summary>
|
||||||
|
public static DateTime ConvertFromMicroseconds(decimal microseconds) => _epoch.AddTicks((long)Math.Round(microseconds * _ticksPerMicrosecond));
|
||||||
|
/// <summary>
|
||||||
|
/// Convert a nanoseconds since epoch (01-01-1970) value to DateTime
|
||||||
|
/// </summary>
|
||||||
|
public static DateTime ConvertFromMicroseconds(double microseconds) => ConvertFromMicroseconds((decimal)microseconds);
|
||||||
|
/// <summary>
|
||||||
|
/// Convert a nanoseconds since epoch (01-01-1970) value to DateTime
|
||||||
|
/// </summary>
|
||||||
|
public static DateTime ConvertFromMicroseconds(long microseconds) => ConvertFromMicroseconds((decimal)microseconds);
|
||||||
|
/// <summary>
|
||||||
|
/// Convert a nanoseconds since epoch (01-01-1970) value to DateTime
|
||||||
|
/// </summary>
|
||||||
|
public static DateTime ConvertFromNanoseconds(decimal nanoseconds) => _epoch.AddTicks((long)Math.Round(nanoseconds * _ticksPerNanosecond));
|
||||||
|
/// <summary>
|
||||||
|
/// Convert a nanoseconds since epoch (01-01-1970) value to DateTime
|
||||||
|
/// </summary>
|
||||||
|
public static DateTime ConvertFromNanoseconds(double nanoseconds) => ConvertFromNanoseconds((decimal)nanoseconds);
|
||||||
|
/// <summary>
|
||||||
|
/// Convert a nanoseconds since epoch (01-01-1970) value to DateTime
|
||||||
|
/// </summary>
|
||||||
|
public static DateTime ConvertFromNanoseconds(long nanoseconds) => ConvertFromNanoseconds((decimal)nanoseconds);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Convert a DateTime value to seconds since epoch (01-01-1970) value
|
/// Convert a DateTime value to seconds since epoch (01-01-1970) value
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="time"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
[return: NotNullIfNotNull("time")]
|
[return: NotNullIfNotNull("time")]
|
||||||
public static long? ConvertToSeconds(DateTime? time) => time == null ? null : (long)Math.Round((time.Value - _epoch).TotalSeconds);
|
public static long? ConvertToSeconds(DateTime? time) => time == null ? null : (long)Math.Round((time.Value - _epoch).TotalSeconds);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Convert a DateTime value to milliseconds since epoch (01-01-1970) value
|
/// Convert a DateTime value to milliseconds since epoch (01-01-1970) value
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="time"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
[return: NotNullIfNotNull("time")]
|
[return: NotNullIfNotNull("time")]
|
||||||
public static long? ConvertToMilliseconds(DateTime? time) => time == null ? null : (long)Math.Round((time.Value - _epoch).TotalMilliseconds);
|
public static long? ConvertToMilliseconds(DateTime? time) => time == null ? null : (long)Math.Round((time.Value - _epoch).TotalMilliseconds);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Convert a DateTime value to microseconds since epoch (01-01-1970) value
|
/// Convert a DateTime value to microseconds since epoch (01-01-1970) value
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="time"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
[return: NotNullIfNotNull("time")]
|
[return: NotNullIfNotNull("time")]
|
||||||
public static long? ConvertToMicroseconds(DateTime? time) => time == null ? null : (long)Math.Round((time.Value - _epoch).Ticks / _ticksPerMicrosecond);
|
public static long? ConvertToMicroseconds(DateTime? time) => time == null ? null : (long)Math.Round((time.Value - _epoch).Ticks / _ticksPerMicrosecond);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Convert a DateTime value to nanoseconds since epoch (01-01-1970) value
|
/// Convert a DateTime value to nanoseconds since epoch (01-01-1970) value
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="time"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
[return: NotNullIfNotNull("time")]
|
[return: NotNullIfNotNull("time")]
|
||||||
public static long? ConvertToNanoseconds(DateTime? time) => time == null ? null : (long)Math.Round((time.Value - _epoch).Ticks / _ticksPerNanosecond);
|
public static long? ConvertToNanoseconds(DateTime? time) => time == null ? null : (long)Math.Round((time.Value - _epoch).Ticks / _ticksPerNanosecond);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>netstandard2.0;netstandard2.1;net8.0;net9.0</TargetFrameworks>
|
<TargetFrameworks>netstandard2.0;netstandard2.1;net8.0;net9.0</TargetFrameworks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
@ -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.9.0</PackageVersion>
|
<PackageVersion>9.10.0</PackageVersion>
|
||||||
<AssemblyVersion>9.9.0</AssemblyVersion>
|
<AssemblyVersion>9.10.0</AssemblyVersion>
|
||||||
<FileVersion>9.9.0</FileVersion>
|
<FileVersion>9.10.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;CryptoExchange.Net</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;CryptoExchange.Net</PackageTags>
|
||||||
<RepositoryType>git</RepositoryType>
|
<RepositoryType>git</RepositoryType>
|
||||||
@ -51,11 +51,11 @@
|
|||||||
</PackageReference>
|
</PackageReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.6" />
|
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.10" />
|
||||||
<PackageReference Include="System.Text.Json" Version="9.0.6" />
|
<PackageReference Include="System.Text.Json" Version="9.0.10" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup Label="Transitive Client Packages">
|
<ItemGroup Label="Transitive Client Packages">
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="9.0.6" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="9.0.10" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.6" />
|
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.10" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
@ -399,7 +399,7 @@ namespace CryptoExchange.Net
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether the trading mode is linear
|
/// Whether the trading mode is linear
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static bool IsLinear(this TradingMode type) => type == TradingMode.PerpetualLinear || type == TradingMode.DeliveryLinear;
|
public static bool IsLinear(this TradingMode type) => type == TradingMode.PerpetualLinear || type == TradingMode.DeliveryLinear;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether the trading mode is inverse
|
/// Whether the trading mode is inverse
|
||||||
@ -416,6 +416,36 @@ namespace CryptoExchange.Net
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static bool IsDelivery(this TradingMode type) => type == TradingMode.DeliveryInverse || type == TradingMode.DeliveryLinear;
|
public static bool IsDelivery(this TradingMode type) => type == TradingMode.DeliveryInverse || type == TradingMode.DeliveryLinear;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether the account type is a futures account
|
||||||
|
/// </summary>
|
||||||
|
public static bool IsFuturesAccount(this SharedAccountType type) =>
|
||||||
|
type == SharedAccountType.PerpetualLinearFutures
|
||||||
|
|| type == SharedAccountType.DeliveryLinearFutures
|
||||||
|
|| type == SharedAccountType.PerpetualInverseFutures
|
||||||
|
|| type == SharedAccountType.DeliveryInverseFutures;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether the account type is a margin account
|
||||||
|
/// </summary>
|
||||||
|
public static bool IsMarginAccount(this SharedAccountType type) =>
|
||||||
|
type == SharedAccountType.CrossMargin
|
||||||
|
|| type == SharedAccountType.IsolatedMargin;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Map a TradingMode value to a SharedAccountType enum value
|
||||||
|
/// </summary>
|
||||||
|
public static SharedAccountType ToAccountType(this TradingMode mode)
|
||||||
|
{
|
||||||
|
if (mode == TradingMode.Spot) return SharedAccountType.Spot;
|
||||||
|
if (mode == TradingMode.PerpetualLinear) return SharedAccountType.PerpetualLinearFutures;
|
||||||
|
if (mode == TradingMode.PerpetualInverse) return SharedAccountType.PerpetualInverseFutures;
|
||||||
|
if (mode == TradingMode.DeliveryInverse) return SharedAccountType.DeliveryInverseFutures;
|
||||||
|
if (mode == TradingMode.DeliveryLinear) return SharedAccountType.DeliveryLinearFutures;
|
||||||
|
|
||||||
|
throw new ArgumentException(nameof(mode), "Unmapped trading mode");
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Register rest client interfaces
|
/// Register rest client interfaces
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -445,6 +475,8 @@ namespace CryptoExchange.Net
|
|||||||
services.AddTransient(x => (IFeeRestClient)client(x)!);
|
services.AddTransient(x => (IFeeRestClient)client(x)!);
|
||||||
if (typeof(IBookTickerRestClient).IsAssignableFrom(typeof(T)))
|
if (typeof(IBookTickerRestClient).IsAssignableFrom(typeof(T)))
|
||||||
services.AddTransient(x => (IBookTickerRestClient)client(x)!);
|
services.AddTransient(x => (IBookTickerRestClient)client(x)!);
|
||||||
|
if (typeof(ITransferRestClient).IsAssignableFrom(typeof(T)))
|
||||||
|
services.AddTransient(x => (ITransferRestClient)client(x)!);
|
||||||
|
|
||||||
if (typeof(ISpotOrderRestClient).IsAssignableFrom(typeof(T)))
|
if (typeof(ISpotOrderRestClient).IsAssignableFrom(typeof(T)))
|
||||||
services.AddTransient(x => (ISpotOrderRestClient)client(x)!);
|
services.AddTransient(x => (ISpotOrderRestClient)client(x)!);
|
||||||
|
|||||||
63
CryptoExchange.Net/SharedApis/Enums/SharedAccountType.cs
Normal file
63
CryptoExchange.Net/SharedApis/Enums/SharedAccountType.cs
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace CryptoExchange.Net.SharedApis
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Account type
|
||||||
|
/// </summary>
|
||||||
|
public enum SharedAccountType
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Unified account, combined account for multiple different types of trading
|
||||||
|
/// </summary>
|
||||||
|
Unified,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Funding account, where withdrawals and deposits are made from and to
|
||||||
|
/// </summary>
|
||||||
|
Funding,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Spot trading account
|
||||||
|
/// </summary>
|
||||||
|
Spot,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Cross margin account
|
||||||
|
/// </summary>
|
||||||
|
CrossMargin,
|
||||||
|
/// <summary>
|
||||||
|
/// Isolated margin account
|
||||||
|
/// </summary>
|
||||||
|
IsolatedMargin,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Perpetual linear futures account
|
||||||
|
/// </summary>
|
||||||
|
PerpetualLinearFutures,
|
||||||
|
/// <summary>
|
||||||
|
/// Delivery linear futures account
|
||||||
|
/// </summary>
|
||||||
|
DeliveryLinearFutures,
|
||||||
|
/// <summary>
|
||||||
|
/// Perpetual inverse futures account
|
||||||
|
/// </summary>
|
||||||
|
PerpetualInverseFutures,
|
||||||
|
/// <summary>
|
||||||
|
/// Delivery inverse futures account
|
||||||
|
/// </summary>
|
||||||
|
DeliveryInverseFutures,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Option account
|
||||||
|
/// </summary>
|
||||||
|
Option,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Other
|
||||||
|
/// </summary>
|
||||||
|
Other
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -12,7 +12,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Balances request options
|
/// Balances request options
|
||||||
/// </summary>
|
/// </summary>
|
||||||
EndpointOptions<GetBalancesRequest> GetBalancesOptions { get; }
|
GetBalancesOptions GetBalancesOptions { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get balances for the user
|
/// Get balances for the user
|
||||||
|
|||||||
@ -0,0 +1,25 @@
|
|||||||
|
using CryptoExchange.Net.Objects;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace CryptoExchange.Net.SharedApis
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Client for transferring funds between account types
|
||||||
|
/// </summary>
|
||||||
|
public interface ITransferRestClient : ISharedClient
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Transfer request options
|
||||||
|
/// </summary>
|
||||||
|
TransferOptions TransferOptions { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Transfer funds between account types
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request">Request info</param>
|
||||||
|
/// <param name="ct">Cancellation token</param>
|
||||||
|
Task<ExchangeWebResult<SharedId>> TransferAsync(TransferRequest request, CancellationToken ct = default);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,96 @@
|
|||||||
|
using CryptoExchange.Net.Objects;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace CryptoExchange.Net.SharedApis
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Options for requesting a transfer
|
||||||
|
/// </summary>
|
||||||
|
public class GetBalancesOptions : EndpointOptions<GetBalancesRequest>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Supported account types
|
||||||
|
/// </summary>
|
||||||
|
public AccountTypeFilter[] SupportedAccountTypes { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ctor
|
||||||
|
/// </summary>
|
||||||
|
public GetBalancesOptions(params AccountTypeFilter[] accountTypes) : base(true)
|
||||||
|
{
|
||||||
|
SupportedAccountTypes = accountTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Validate a request
|
||||||
|
/// </summary>
|
||||||
|
public Error? ValidateRequest(
|
||||||
|
string exchange,
|
||||||
|
GetBalancesRequest request,
|
||||||
|
TradingMode[] supportedApiTypes)
|
||||||
|
{
|
||||||
|
if (request.AccountType != null && !IsValid(request.AccountType.Value))
|
||||||
|
return ArgumentError.Invalid(nameof(request.AccountType), "Invalid AccountType");
|
||||||
|
|
||||||
|
return base.ValidateRequest(exchange, request, null, supportedApiTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Is the account type valid for this client
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="accountType"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public bool IsValid(SharedAccountType accountType)
|
||||||
|
{
|
||||||
|
if (accountType == SharedAccountType.Funding)
|
||||||
|
return SupportedAccountTypes.Contains(AccountTypeFilter.Funding);
|
||||||
|
|
||||||
|
if (accountType == SharedAccountType.Spot)
|
||||||
|
return SupportedAccountTypes.Contains(AccountTypeFilter.Spot);
|
||||||
|
|
||||||
|
if (accountType == SharedAccountType.PerpetualLinearFutures
|
||||||
|
|| accountType == SharedAccountType.PerpetualInverseFutures
|
||||||
|
|| accountType == SharedAccountType.DeliveryLinearFutures
|
||||||
|
|| accountType == SharedAccountType.DeliveryInverseFutures)
|
||||||
|
{
|
||||||
|
return SupportedAccountTypes.Contains(AccountTypeFilter.Futures);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (accountType == SharedAccountType.CrossMargin
|
||||||
|
|| accountType == SharedAccountType.IsolatedMargin)
|
||||||
|
{
|
||||||
|
return SupportedAccountTypes.Contains(AccountTypeFilter.Margin);
|
||||||
|
}
|
||||||
|
|
||||||
|
return SupportedAccountTypes.Contains(AccountTypeFilter.Option);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Account type filter
|
||||||
|
/// </summary>
|
||||||
|
public enum AccountTypeFilter
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Funding account
|
||||||
|
/// </summary>
|
||||||
|
Funding,
|
||||||
|
/// <summary>
|
||||||
|
/// Spot account
|
||||||
|
/// </summary>
|
||||||
|
Spot,
|
||||||
|
/// <summary>
|
||||||
|
/// Futures account
|
||||||
|
/// </summary>
|
||||||
|
Futures,
|
||||||
|
/// <summary>
|
||||||
|
/// Margin account
|
||||||
|
/// </summary>
|
||||||
|
Margin,
|
||||||
|
/// <summary>
|
||||||
|
/// Option account
|
||||||
|
/// </summary>
|
||||||
|
Option
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,42 @@
|
|||||||
|
using CryptoExchange.Net.Objects;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace CryptoExchange.Net.SharedApis
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Options for requesting a transfer
|
||||||
|
/// </summary>
|
||||||
|
public class TransferOptions : EndpointOptions<TransferRequest>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Supported account types
|
||||||
|
/// </summary>
|
||||||
|
public SharedAccountType[] SupportedAccountTypes { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ctor
|
||||||
|
/// </summary>
|
||||||
|
public TransferOptions(SharedAccountType[] accountTypes) : base(true)
|
||||||
|
{
|
||||||
|
SupportedAccountTypes = accountTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Validate a request
|
||||||
|
/// </summary>
|
||||||
|
public new Error? ValidateRequest(
|
||||||
|
string exchange,
|
||||||
|
TransferRequest request,
|
||||||
|
TradingMode? tradingMode,
|
||||||
|
TradingMode[] supportedApiTypes)
|
||||||
|
{
|
||||||
|
if (!SupportedAccountTypes.Contains(request.FromAccountType))
|
||||||
|
return ArgumentError.Invalid(nameof(request.FromAccountType), "Invalid FromAccountType");
|
||||||
|
|
||||||
|
if (!SupportedAccountTypes.Contains(request.ToAccountType))
|
||||||
|
return ArgumentError.Invalid(nameof(request.FromAccountType), "Invalid ToAccountType");
|
||||||
|
|
||||||
|
return base.ValidateRequest(exchange, request, tradingMode, supportedApiTypes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -8,18 +8,28 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
public record GetBalancesRequest : SharedRequest
|
public record GetBalancesRequest : SharedRequest
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Trading mode
|
/// Account type
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public TradingMode? TradingMode { get; set; }
|
public SharedAccountType? AccountType { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="tradingMode">Trading mode</param>
|
/// <param name="tradingMode">Trading mode</param>
|
||||||
/// <param name="exchangeParameters">Exchange specific parameters</param>
|
/// <param name="exchangeParameters">Exchange specific parameters</param>
|
||||||
public GetBalancesRequest(TradingMode? tradingMode = null, ExchangeParameters? exchangeParameters = null) : base(exchangeParameters)
|
public GetBalancesRequest(TradingMode tradingMode, ExchangeParameters? exchangeParameters = null) : base(exchangeParameters)
|
||||||
{
|
{
|
||||||
TradingMode = tradingMode;
|
AccountType = tradingMode.ToAccountType();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ctor
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="accountType">Account type</param>
|
||||||
|
/// <param name="exchangeParameters">Exchange specific parameters</param>
|
||||||
|
public GetBalancesRequest(SharedAccountType? accountType = null, ExchangeParameters? exchangeParameters = null) : base(exchangeParameters)
|
||||||
|
{
|
||||||
|
AccountType = accountType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
61
CryptoExchange.Net/SharedApis/Models/Rest/TransferRequest.cs
Normal file
61
CryptoExchange.Net/SharedApis/Models/Rest/TransferRequest.cs
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
namespace CryptoExchange.Net.SharedApis
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Request to transfer funds between account types
|
||||||
|
/// </summary>
|
||||||
|
public record TransferRequest : SharedRequest
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Asset
|
||||||
|
/// </summary>
|
||||||
|
public string Asset { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Quantity
|
||||||
|
/// </summary>
|
||||||
|
public decimal Quantity { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// From symbol
|
||||||
|
/// </summary>
|
||||||
|
public string? FromSymbol { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// To symbol
|
||||||
|
/// </summary>
|
||||||
|
public string? ToSymbol { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// From account type
|
||||||
|
/// </summary>
|
||||||
|
public SharedAccountType FromAccountType { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// To account type
|
||||||
|
/// </summary>
|
||||||
|
public SharedAccountType ToAccountType { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ctor
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="asset">The asset to transfer</param>
|
||||||
|
/// <param name="quantity">Quantity to transfer</param>
|
||||||
|
/// <param name="fromAccount">From account type</param>
|
||||||
|
/// <param name="toAccount">To account type</param>
|
||||||
|
/// <param name="fromSymbol">From symbol</param>
|
||||||
|
/// <param name="toSymbol">To symbol</param>
|
||||||
|
/// <param name="exchangeParameters">Exchange specific parameters</param>
|
||||||
|
public TransferRequest(
|
||||||
|
string asset,
|
||||||
|
decimal quantity,
|
||||||
|
SharedAccountType fromAccount,
|
||||||
|
SharedAccountType toAccount,
|
||||||
|
string? fromSymbol = null,
|
||||||
|
string? toSymbol = null,
|
||||||
|
ExchangeParameters? exchangeParameters = null) : base(exchangeParameters)
|
||||||
|
{
|
||||||
|
Asset = asset;
|
||||||
|
Quantity = quantity;
|
||||||
|
FromAccountType = fromAccount;
|
||||||
|
ToAccountType = toAccount;
|
||||||
|
FromSymbol = fromSymbol;
|
||||||
|
ToSymbol = toSymbol;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -17,6 +17,7 @@
|
|||||||
/// Total quantity
|
/// Total quantity
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public decimal Total { get; set; }
|
public decimal Total { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Isolated margin symbol, only applicable for isolated margin futures
|
/// Isolated margin symbol, only applicable for isolated margin futures
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -28,6 +28,10 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string OrderId { get; set; }
|
public string OrderId { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// The client order id
|
||||||
|
/// </summary>
|
||||||
|
public string? ClientOrderId { get; set; }
|
||||||
|
/// <summary>
|
||||||
/// Side of the trade
|
/// Side of the trade
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public SharedOrderSide? Side { get; set; }
|
public SharedOrderSide? Side { get; set; }
|
||||||
|
|||||||
@ -415,7 +415,7 @@ namespace CryptoExchange.Net.Testing.Comparers
|
|||||||
var value = jsonValue.GetDecimal();
|
var value = jsonValue.GetDecimal();
|
||||||
if (objectValue is DateTime time)
|
if (objectValue is DateTime time)
|
||||||
{
|
{
|
||||||
if (time != DateTimeConverter.ParseFromDouble((double)value))
|
if (time != DateTimeConverter.ParseFromDecimal(value))
|
||||||
throw new Exception($"{method}: {property} not equal: {DateTimeConverter.ParseFromDouble((double)value!)} vs {time}");
|
throw new Exception($"{method}: {property} not equal: {DateTimeConverter.ParseFromDouble((double)value!)} vs {time}");
|
||||||
}
|
}
|
||||||
else if (propertyType.IsEnum || Nullable.GetUnderlyingType(propertyType)?.IsEnum == true)
|
else if (propertyType.IsEnum || Nullable.GetUnderlyingType(propertyType)?.IsEnum == true)
|
||||||
|
|||||||
@ -325,9 +325,12 @@ namespace CryptoExchange.Net.Trackers.Trades
|
|||||||
if (Period != null)
|
if (Period != null)
|
||||||
items = items.Where(e => e.Timestamp >= DateTime.UtcNow.Add(-Period.Value));
|
items = items.Where(e => e.Timestamp >= DateTime.UtcNow.Add(-Period.Value));
|
||||||
|
|
||||||
_snapshotId = data.Max(d => d.Timestamp.Ticks);
|
if (items.Any())
|
||||||
foreach (var item in items.OrderBy(d => d.Timestamp))
|
{
|
||||||
_data.Add(item);
|
_snapshotId = data.Max(d => d.Timestamp.Ticks);
|
||||||
|
foreach (var item in items.OrderBy(d => d.Timestamp))
|
||||||
|
_data.Add(item);
|
||||||
|
}
|
||||||
|
|
||||||
_snapshotSet = true;
|
_snapshotSet = true;
|
||||||
_changed = true;
|
_changed = true;
|
||||||
|
|||||||
@ -5,31 +5,32 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Binance.Net" Version="11.8.0" />
|
<PackageReference Include="Binance.Net" Version="11.9.0" />
|
||||||
<PackageReference Include="Bitfinex.Net" Version="9.8.0" />
|
<PackageReference Include="Bitfinex.Net" Version="9.9.0" />
|
||||||
<PackageReference Include="BitMart.Net" Version="2.9.0" />
|
<PackageReference Include="BitMart.Net" Version="2.10.0" />
|
||||||
<PackageReference Include="BloFin.Net" Version="1.1.0" />
|
<PackageReference Include="BloFin.Net" Version="1.2.0" />
|
||||||
<PackageReference Include="Bybit.Net" Version="5.9.0" />
|
<PackageReference Include="Bybit.Net" Version="5.10.1" />
|
||||||
<PackageReference Include="CoinEx.Net" Version="9.8.0" />
|
<PackageReference Include="CoinEx.Net" Version="9.9.0" />
|
||||||
<PackageReference Include="CoinW.Net" Version="1.5.0" />
|
<PackageReference Include="CoinW.Net" Version="1.6.0" />
|
||||||
<PackageReference Include="CryptoCom.Net" Version="2.9.0" />
|
<PackageReference Include="CryptoCom.Net" Version="2.10.0" />
|
||||||
<PackageReference Include="DeepCoin.Net" Version="2.8.0" />
|
<PackageReference Include="DeepCoin.Net" Version="2.9.0" />
|
||||||
<PackageReference Include="GateIo.Net" Version="2.9.1" />
|
<PackageReference Include="GateIo.Net" Version="2.11.0" />
|
||||||
<PackageReference Include="HyperLiquid.Net" Version="2.13.0" />
|
<PackageReference Include="HyperLiquid.Net" Version="2.14.0" />
|
||||||
<PackageReference Include="JK.BingX.Net" Version="2.8.0" />
|
<PackageReference Include="JK.BingX.Net" Version="2.9.0" />
|
||||||
<PackageReference Include="JK.Bitget.Net" Version="2.8.0" />
|
<PackageReference Include="JK.Bitget.Net" Version="2.9.0" />
|
||||||
<PackageReference Include="JK.Mexc.Net" Version="3.9.0" />
|
<PackageReference Include="JK.Mexc.Net" Version="3.10.0" />
|
||||||
<PackageReference Include="JK.OKX.Net" Version="3.8.0" />
|
<PackageReference Include="JK.OKX.Net" Version="3.9.0" />
|
||||||
<PackageReference Include="Jkorf.Aster.Net" Version="1.0.0" />
|
<PackageReference Include="Jkorf.Aster.Net" Version="1.1.0" />
|
||||||
<PackageReference Include="JKorf.BitMEX.Net" Version="2.8.0" />
|
<PackageReference Include="JKorf.BitMEX.Net" Version="2.9.0" />
|
||||||
<PackageReference Include="JKorf.Coinbase.Net" Version="2.8.0" />
|
<PackageReference Include="JKorf.Coinbase.Net" Version="2.9.0" />
|
||||||
<PackageReference Include="JKorf.HTX.Net" Version="7.8.0" />
|
<PackageReference Include="JKorf.HTX.Net" Version="7.9.0" />
|
||||||
<PackageReference Include="KrakenExchange.Net" Version="6.8.0" />
|
<PackageReference Include="JKorf.Upbit.Net" Version="1.0.0" />
|
||||||
<PackageReference Include="Kucoin.Net" Version="7.8.0" />
|
<PackageReference Include="KrakenExchange.Net" Version="6.9.0" />
|
||||||
|
<PackageReference Include="Kucoin.Net" Version="7.9.0" />
|
||||||
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
|
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
|
||||||
<PackageReference Include="Toobit.Net" Version="1.7.0" />
|
<PackageReference Include="Toobit.Net" Version="1.8.0" />
|
||||||
<PackageReference Include="WhiteBit.Net" Version="2.9.0" />
|
<PackageReference Include="WhiteBit.Net" Version="2.10.0" />
|
||||||
<PackageReference Include="XT.Net" Version="2.8.0" />
|
<PackageReference Include="XT.Net" Version="2.9.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@ -21,6 +21,7 @@
|
|||||||
@inject IMexcRestClient mexcClient
|
@inject IMexcRestClient mexcClient
|
||||||
@inject IOKXRestClient okxClient
|
@inject IOKXRestClient okxClient
|
||||||
@inject IToobitRestClient toobitClient
|
@inject IToobitRestClient toobitClient
|
||||||
|
@inject IUpbitRestClient upbitClient
|
||||||
@inject IWhiteBitRestClient whitebitClient
|
@inject IWhiteBitRestClient whitebitClient
|
||||||
@inject IXTRestClient xtClient
|
@inject IXTRestClient xtClient
|
||||||
|
|
||||||
@ -57,6 +58,7 @@
|
|||||||
var mexcTask = mexcClient.SpotApi.ExchangeData.GetTickerAsync("BTCUSDT");
|
var mexcTask = mexcClient.SpotApi.ExchangeData.GetTickerAsync("BTCUSDT");
|
||||||
var okxTask = okxClient.UnifiedApi.ExchangeData.GetTickerAsync("BTC-USDT");
|
var okxTask = okxClient.UnifiedApi.ExchangeData.GetTickerAsync("BTC-USDT");
|
||||||
var toobitTask = toobitClient.SpotApi.ExchangeData.GetTickersAsync("BTCUSDT");
|
var toobitTask = toobitClient.SpotApi.ExchangeData.GetTickersAsync("BTCUSDT");
|
||||||
|
var upbitTask = upbitClient.SpotApi.ExchangeData.GetTickerAsync("USDT-BTC");
|
||||||
var whitebitTask = whitebitClient.V4Api.ExchangeData.GetTickersAsync();
|
var whitebitTask = whitebitClient.V4Api.ExchangeData.GetTickersAsync();
|
||||||
var xtTask = xtClient.SpotApi.ExchangeData.GetTickersAsync("btc_usdt");
|
var xtTask = xtClient.SpotApi.ExchangeData.GetTickersAsync("btc_usdt");
|
||||||
|
|
||||||
@ -136,6 +138,9 @@
|
|||||||
if (toobitTask.Result.Success)
|
if (toobitTask.Result.Success)
|
||||||
_prices.Add("Toobit", toobitTask.Result.Data.Single().LastPrice ?? 0);
|
_prices.Add("Toobit", toobitTask.Result.Data.Single().LastPrice ?? 0);
|
||||||
|
|
||||||
|
if (upbitTask.Result.Success)
|
||||||
|
_prices.Add("Upbit", upbitTask.Result.Data.LastPrice);
|
||||||
|
|
||||||
if (whitebitTask.Result.Success){
|
if (whitebitTask.Result.Success){
|
||||||
// WhiteBit API doesn't offer an endpoint to filter for a specific ticker, so we have to filter client side
|
// WhiteBit API doesn't offer an endpoint to filter for a specific ticker, so we have to filter client side
|
||||||
var tickers = whitebitTask.Result.Data;
|
var tickers = whitebitTask.Result.Data;
|
||||||
|
|||||||
@ -21,6 +21,7 @@
|
|||||||
@inject IMexcSocketClient mexcSocketClient
|
@inject IMexcSocketClient mexcSocketClient
|
||||||
@inject IOKXSocketClient okxSocketClient
|
@inject IOKXSocketClient okxSocketClient
|
||||||
@inject IToobitSocketClient toobitSocketClient
|
@inject IToobitSocketClient toobitSocketClient
|
||||||
|
@inject IUpbitSocketClient upbitSocketClient
|
||||||
@inject IWhiteBitSocketClient whitebitSocketClient
|
@inject IWhiteBitSocketClient whitebitSocketClient
|
||||||
@inject IXTSocketClient xtSocketClient
|
@inject IXTSocketClient xtSocketClient
|
||||||
@using System.Collections.Concurrent
|
@using System.Collections.Concurrent
|
||||||
@ -72,6 +73,7 @@
|
|||||||
okxSocketClient.UnifiedApi.ExchangeData.SubscribeToTickerUpdatesAsync("ETH-BTC", data => UpdateData("OKX", data.Data.LastPrice ?? 0)),
|
okxSocketClient.UnifiedApi.ExchangeData.SubscribeToTickerUpdatesAsync("ETH-BTC", data => UpdateData("OKX", data.Data.LastPrice ?? 0)),
|
||||||
// Toobit doesn't support the ETH/BTC pair
|
// Toobit doesn't support the ETH/BTC pair
|
||||||
//toobitSocketClient.SpotApi.SubscribeToTickerUpdatesAsync("ETHBTC", data => UpdateData("Toobit", data.Data.LastPrice ?? 0)),
|
//toobitSocketClient.SpotApi.SubscribeToTickerUpdatesAsync("ETHBTC", data => UpdateData("Toobit", data.Data.LastPrice ?? 0)),
|
||||||
|
upbitSocketClient.SpotApi.SubscribeToTickerUpdatesAsync("BTC-ETH", data => UpdateData("Upbit", data.Data.LastPrice)),
|
||||||
whitebitSocketClient.V4Api.SubscribeToTickerUpdatesAsync("ETH_BTC", data => UpdateData("WhiteBit", data.Data.Ticker.LastPrice)),
|
whitebitSocketClient.V4Api.SubscribeToTickerUpdatesAsync("ETH_BTC", data => UpdateData("WhiteBit", data.Data.Ticker.LastPrice)),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -25,6 +25,7 @@
|
|||||||
@using Kucoin.Net.Interfaces
|
@using Kucoin.Net.Interfaces
|
||||||
@using Mexc.Net.Interfaces
|
@using Mexc.Net.Interfaces
|
||||||
@using OKX.Net.Interfaces;
|
@using OKX.Net.Interfaces;
|
||||||
|
@using Upbit.Net.Interfaces;
|
||||||
@using Toobit.Net.Interfaces;
|
@using Toobit.Net.Interfaces;
|
||||||
@using WhiteBit.Net.Interfaces
|
@using WhiteBit.Net.Interfaces
|
||||||
@using XT.Net.Interfaces
|
@using XT.Net.Interfaces
|
||||||
@ -50,6 +51,7 @@
|
|||||||
@inject IMexcOrderBookFactory mexcFactory
|
@inject IMexcOrderBookFactory mexcFactory
|
||||||
@inject IOKXOrderBookFactory okxFactory
|
@inject IOKXOrderBookFactory okxFactory
|
||||||
@inject IToobitOrderBookFactory toobitFactory
|
@inject IToobitOrderBookFactory toobitFactory
|
||||||
|
@inject IUpbitOrderBookFactory upbitFactory
|
||||||
@inject IWhiteBitOrderBookFactory whitebitFactory
|
@inject IWhiteBitOrderBookFactory whitebitFactory
|
||||||
@inject IXTOrderBookFactory xtFactory
|
@inject IXTOrderBookFactory xtFactory
|
||||||
@implements IDisposable
|
@implements IDisposable
|
||||||
@ -107,6 +109,7 @@
|
|||||||
{ "Mexc", mexcFactory.CreateSpot("ETHBTC") },
|
{ "Mexc", mexcFactory.CreateSpot("ETHBTC") },
|
||||||
{ "OKX", okxFactory.Create("ETH-BTC") },
|
{ "OKX", okxFactory.Create("ETH-BTC") },
|
||||||
{ "Toobit", toobitFactory.CreateSpot("ETHUSDT") },
|
{ "Toobit", toobitFactory.CreateSpot("ETHUSDT") },
|
||||||
|
{ "Upbit", upbitFactory.CreateSpot("BTC-ETH") },
|
||||||
{ "WhiteBit", whitebitFactory.CreateV4("ETH_BTC") },
|
{ "WhiteBit", whitebitFactory.CreateV4("ETH_BTC") },
|
||||||
{ "XT", xtFactory.CreateSpot("eth_btc") },
|
{ "XT", xtFactory.CreateSpot("eth_btc") },
|
||||||
};
|
};
|
||||||
|
|||||||
@ -26,6 +26,7 @@
|
|||||||
@using Kucoin.Net.Interfaces
|
@using Kucoin.Net.Interfaces
|
||||||
@using Mexc.Net.Interfaces
|
@using Mexc.Net.Interfaces
|
||||||
@using OKX.Net.Interfaces;
|
@using OKX.Net.Interfaces;
|
||||||
|
@using Upbit.Net.Interfaces;
|
||||||
@using Toobit.Net.Interfaces;
|
@using Toobit.Net.Interfaces;
|
||||||
@using WhiteBit.Net.Interfaces
|
@using WhiteBit.Net.Interfaces
|
||||||
@using XT.Net.Interfaces
|
@using XT.Net.Interfaces
|
||||||
@ -51,11 +52,12 @@
|
|||||||
@inject IMexcTrackerFactory mexcFactory
|
@inject IMexcTrackerFactory mexcFactory
|
||||||
@inject IOKXTrackerFactory okxFactory
|
@inject IOKXTrackerFactory okxFactory
|
||||||
@inject IToobitTrackerFactory toobitFactory
|
@inject IToobitTrackerFactory toobitFactory
|
||||||
|
@inject IUpbitTrackerFactory upbitFactory
|
||||||
@inject IWhiteBitTrackerFactory whitebitFactory
|
@inject IWhiteBitTrackerFactory whitebitFactory
|
||||||
@inject IXTTrackerFactory xtFactory
|
@inject IXTTrackerFactory xtFactory
|
||||||
@implements IDisposable
|
@implements IDisposable
|
||||||
|
|
||||||
<h3>ETH-BTC trade Trackers, live updates:</h3>
|
<h3>Trade Trackers, live updates:</h3>
|
||||||
<div style="display:flex; flex-wrap: wrap;">
|
<div style="display:flex; flex-wrap: wrap;">
|
||||||
@foreach (var tracker in _trackers.OrderBy(p => p.Exchange))
|
@foreach (var tracker in _trackers.OrderBy(p => p.Exchange))
|
||||||
{
|
{
|
||||||
@ -103,11 +105,12 @@
|
|||||||
{ mexcFactory.CreateTradeTracker(usdtSpotSymbol, period: TimeSpan.FromMinutes(5)) },
|
{ mexcFactory.CreateTradeTracker(usdtSpotSymbol, period: TimeSpan.FromMinutes(5)) },
|
||||||
{ okxFactory.CreateTradeTracker(usdtSpotSymbol, period: TimeSpan.FromMinutes(5)) },
|
{ okxFactory.CreateTradeTracker(usdtSpotSymbol, period: TimeSpan.FromMinutes(5)) },
|
||||||
{ toobitFactory.CreateTradeTracker(usdtSpotSymbol, period: TimeSpan.FromMinutes(5)) },
|
{ toobitFactory.CreateTradeTracker(usdtSpotSymbol, period: TimeSpan.FromMinutes(5)) },
|
||||||
|
{ upbitFactory.CreateTradeTracker(usdtSpotSymbol, period: TimeSpan.FromMinutes(5)) },
|
||||||
{ whitebitFactory.CreateTradeTracker(usdtSpotSymbol, period: TimeSpan.FromMinutes(5)) },
|
{ whitebitFactory.CreateTradeTracker(usdtSpotSymbol, period: TimeSpan.FromMinutes(5)) },
|
||||||
{ xtFactory.CreateTradeTracker(usdtSpotSymbol, period: TimeSpan.FromMinutes(5)) },
|
{ xtFactory.CreateTradeTracker(usdtSpotSymbol, period: TimeSpan.FromMinutes(5)) },
|
||||||
};
|
};
|
||||||
|
|
||||||
await Task.WhenAll(_trackers.Select(b => b.StartAsync()));
|
await Task.WhenAll(_trackers.Select(b => b.StartAsync(false)));
|
||||||
|
|
||||||
// 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);
|
||||||
|
|||||||
@ -54,6 +54,7 @@ namespace BlazorClient
|
|||||||
services.AddMexc();
|
services.AddMexc();
|
||||||
services.AddOKX();
|
services.AddOKX();
|
||||||
services.AddToobit();
|
services.AddToobit();
|
||||||
|
services.AddUpbit();
|
||||||
services.AddWhiteBit();
|
services.AddWhiteBit();
|
||||||
services.AddXT();
|
services.AddXT();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,6 +29,7 @@
|
|||||||
@using Kucoin.Net.Interfaces.Clients;
|
@using Kucoin.Net.Interfaces.Clients;
|
||||||
@using Mexc.Net.Interfaces.Clients;
|
@using Mexc.Net.Interfaces.Clients;
|
||||||
@using OKX.Net.Interfaces.Clients;
|
@using OKX.Net.Interfaces.Clients;
|
||||||
|
@using Upbit.Net.Interfaces.Clients;
|
||||||
@using Toobit.Net.Interfaces.Clients;
|
@using Toobit.Net.Interfaces.Clients;
|
||||||
@using WhiteBit.Net.Interfaces.Clients
|
@using WhiteBit.Net.Interfaces.Clients
|
||||||
@using XT.Net.Interfaces.Clients
|
@using XT.Net.Interfaces.Clients
|
||||||
|
|||||||
@ -6,20 +6,20 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Binance.Net" Version="11.1.0" />
|
<PackageReference Include="Binance.Net" Version="11.9.0" />
|
||||||
<PackageReference Include="Bitfinex.Net" Version="9.1.0" />
|
<PackageReference Include="Bitfinex.Net" Version="9.9.0" />
|
||||||
<PackageReference Include="BitMart.Net" Version="2.1.0" />
|
<PackageReference Include="BitMart.Net" Version="2.10.0" />
|
||||||
<PackageReference Include="Bybit.Net" Version="5.1.0" />
|
<PackageReference Include="Bybit.Net" Version="5.10.1" />
|
||||||
<PackageReference Include="CoinEx.Net" Version="9.1.0" />
|
<PackageReference Include="CoinEx.Net" Version="9.9.0" />
|
||||||
<PackageReference Include="CryptoCom.Net" Version="2.1.0" />
|
<PackageReference Include="CryptoCom.Net" Version="2.10.0" />
|
||||||
<PackageReference Include="GateIo.Net" Version="2.1.0" />
|
<PackageReference Include="GateIo.Net" Version="2.11.0" />
|
||||||
<PackageReference Include="JK.Bitget.Net" Version="2.1.0" />
|
<PackageReference Include="JK.Bitget.Net" Version="2.9.0" />
|
||||||
<PackageReference Include="JK.Mexc.Net" Version="3.1.0" />
|
<PackageReference Include="JK.Mexc.Net" Version="3.10.0" />
|
||||||
<PackageReference Include="JK.OKX.Net" Version="3.1.0" />
|
<PackageReference Include="JK.OKX.Net" Version="3.9.0" />
|
||||||
<PackageReference Include="JKorf.Coinbase.Net" Version="2.1.0" />
|
<PackageReference Include="JKorf.Coinbase.Net" Version="2.9.0" />
|
||||||
<PackageReference Include="JKorf.HTX.Net" Version="7.1.0" />
|
<PackageReference Include="JKorf.HTX.Net" Version="7.9.0" />
|
||||||
<PackageReference Include="KrakenExchange.Net" Version="6.1.0" />
|
<PackageReference Include="KrakenExchange.Net" Version="6.9.0" />
|
||||||
<PackageReference Include="Kucoin.Net" Version="7.1.0" />
|
<PackageReference Include="Kucoin.Net" Version="7.9.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@ -8,9 +8,9 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Binance.Net" Version="11.1.0" />
|
<PackageReference Include="Binance.Net" Version="11.9.0" />
|
||||||
<PackageReference Include="BitMart.Net" Version="2.1.0" />
|
<PackageReference Include="BitMart.Net" Version="2.10.0" />
|
||||||
<PackageReference Include="JK.OKX.Net" Version="3.1.0" />
|
<PackageReference Include="JK.OKX.Net" Version="3.9.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@ -35,6 +35,7 @@ Full list of all libraries part of the CryptoExchange.Net ecosystem. Consider us
|
|||||||
||Mexc|CEX|[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|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%|
|
||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%|
|
||||||
||Toobit|CEX|[JKorf/Toobit.Net](https://github.com/JKorf/Toobit.Net)|[](https://www.nuget.org/packages/Toobit.Net)|[Link](https://www.toobit.com/en-US/register?invite_code=zsV19h)|-|
|
||Toobit|CEX|[JKorf/Toobit.Net](https://github.com/JKorf/Toobit.Net)|[](https://www.nuget.org/packages/Toobit.Net)|[Link](https://www.toobit.com/en-US/register?invite_code=zsV19h)|-|
|
||||||
|
||Upbit|CEX|[JKorf/Upbit.Net](https://github.com/JKorf/Upbit.Net)|[](https://www.nuget.org/packages/JKorf.Upbit.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)|-|
|
||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|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%|
|
||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%|
|
||||||
|
|
||||||
@ -65,6 +66,13 @@ 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.10.0 - 15 Oct 2025
|
||||||
|
* Added ITransferRestClient Shared interface
|
||||||
|
* Added ClientOrderId property to SharedUserTrade model
|
||||||
|
* Updated IBalanceRestClient, GetBalancesRequest now mainly works with SharedAccountType type, allowing more options
|
||||||
|
* Updated IBalanceRestClient, GetBalanceOptions now specifies supported account types
|
||||||
|
* Updated DateTimeConverter to work primarily with decimal instead of double to prevent some floating point issues
|
||||||
|
|
||||||
* Version 9.9.0 - 06 Oct 2025
|
* Version 9.9.0 - 06 Oct 2025
|
||||||
* Updated socket Subscription status handling
|
* Updated socket Subscription status handling
|
||||||
* Added SubscriptionStatusChanged event to UpdateSubscription (SubscribeAsync methods reponse)
|
* Added SubscriptionStatusChanged event to UpdateSubscription (SubscribeAsync methods reponse)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user