Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions HTX.Net/Clients/HTXUserClientProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public void ClearUserClients(string userIdentifier)
/// <inheritdoc />
public IHTXRestClient GetRestClient(string userIdentifier, ApiCredentials? credentials = null, HTXEnvironment? environment = null)
{
if (!_restClients.TryGetValue(userIdentifier, out var client))
if (!_restClients.TryGetValue(userIdentifier, out var client) || client.Disposed)
client = CreateRestClient(userIdentifier, credentials, environment);

return client;
Expand All @@ -69,7 +69,7 @@ public IHTXRestClient GetRestClient(string userIdentifier, ApiCredentials? crede
/// <inheritdoc />
public IHTXSocketClient GetSocketClient(string userIdentifier, ApiCredentials? credentials = null, HTXEnvironment? environment = null)
{
if (!_socketClients.TryGetValue(userIdentifier, out var client))
if (!_socketClients.TryGetValue(userIdentifier, out var client) || client.Disposed)
client = CreateSocketClient(userIdentifier, credentials, environment);

return client;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ internal class HTXSocketUsdtFuturesMessageHandler : JsonSocketMessageHandler
{ "accounts_cross.", "accounts_cross" },
{ "orders_cross.", "orders_cross" },
{ "positions_cross.", "positions_cross" },
{ "matchOrders.", "matchOrders" }
{ "matchOrders.", "matchOrders" },
{ "matchOrders_cross.", "matchOrders_cross" }
};

public override JsonSerializerOptions Options { get; } = SerializerOptions.WithConverters(HTXExchange._serializerContext);
Expand Down
48 changes: 47 additions & 1 deletion HTX.Net/Clients/SpotApi/HTXRestClientSpotApiShared.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,44 @@ async Task<ExchangeWebResult<SharedSpotSymbol[]>> ISpotSymbolRestClient.GetSpotS
return response;
}

async Task<ExchangeResult<SharedSymbol[]>> ISpotSymbolRestClient.GetSpotSymbolsForBaseAssetAsync(string baseAsset)
{
if (!ExchangeSymbolCache.HasCached(_topicId))
{
var symbols = await ((ISpotSymbolRestClient)this).GetSpotSymbolsAsync(new GetSymbolsRequest()).ConfigureAwait(false);
if (!symbols)
return new ExchangeResult<SharedSymbol[]>(Exchange, symbols.Error!);
}

return new ExchangeResult<SharedSymbol[]>(Exchange, ExchangeSymbolCache.GetSymbolsForBaseAsset(_topicId, baseAsset));
}

async Task<ExchangeResult<bool>> ISpotSymbolRestClient.SupportsSpotSymbolAsync(SharedSymbol symbol)
{
if (symbol.TradingMode != TradingMode.Spot)
throw new ArgumentException(nameof(symbol), "Only Spot symbols allowed");

if (!ExchangeSymbolCache.HasCached(_topicId))
{
var symbols = await ((ISpotSymbolRestClient)this).GetSpotSymbolsAsync(new GetSymbolsRequest()).ConfigureAwait(false);
if (!symbols)
return new ExchangeResult<bool>(Exchange, symbols.Error!);
}

return new ExchangeResult<bool>(Exchange, ExchangeSymbolCache.SupportsSymbol(_topicId, symbol));
}

async Task<ExchangeResult<bool>> ISpotSymbolRestClient.SupportsSpotSymbolAsync(string symbolName)
{
if (!ExchangeSymbolCache.HasCached(_topicId))
{
var symbols = await ((ISpotSymbolRestClient)this).GetSpotSymbolsAsync(new GetSymbolsRequest()).ConfigureAwait(false);
if (!symbols)
return new ExchangeResult<bool>(Exchange, symbols.Error!);
}

return new ExchangeResult<bool>(Exchange, ExchangeSymbolCache.SupportsSymbol(_topicId, symbolName));
}
#endregion

#region Ticker client
Expand Down Expand Up @@ -706,7 +744,15 @@ async Task<ExchangeWebResult<SharedDeposit[]>> IDepositRestClient.GetDepositsAsy
if (deposits.Data.Count() == (request.Limit ?? 100))
nextToken = new FromIdToken(deposits.Data.Min(x => x.Id - 1).ToString());

return deposits.AsExchangeResult<SharedDeposit[]>(Exchange, TradingMode.Spot, deposits.Data.Select(x => new SharedDeposit(x.Asset!.ToUpperInvariant(), x.Quantity, x.Status == WithdrawDepositStatus.Safe, x.CreateTime)
return deposits.AsExchangeResult<SharedDeposit[]>(Exchange, TradingMode.Spot, deposits.Data.Select(x =>
new SharedDeposit(
x.Asset!.ToUpperInvariant(),
x.Quantity,
x.Status == WithdrawDepositStatus.Safe,
x.CreateTime,
x.Status == WithdrawDepositStatus.Safe ? SharedTransferStatus.Completed
: x.Status == WithdrawDepositStatus.Repealed || x.Status == WithdrawDepositStatus.ConfirmError || x.Status == WithdrawDepositStatus.WalletReject || x.Status == WithdrawDepositStatus.Reject || x.Status == WithdrawDepositStatus.Canceled || x.Status == WithdrawDepositStatus.Failed ? SharedTransferStatus.Failed
: SharedTransferStatus.Failed)
{
Id = x.Id.ToString(),
Network = x.Network,
Expand Down
43 changes: 41 additions & 2 deletions HTX.Net/Clients/UsdtFutures/HTXRestClientUsdtFuturesApiShared.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,15 @@ async Task<ExchangeWebResult<SharedBalance[]>> IBalanceRestClient.GetBalancesAsy
if (!result)
return result.AsExchangeResult<SharedBalance[]>(Exchange, null, default);

return result.AsExchangeResult<SharedBalance[]>(Exchange, SupportedTradingModes, result.Data.Select(x => new SharedBalance(x.MarginAsset, x.MarginBalance, x.MarginFrozen + x.MarginBalance)).ToArray());
return result.AsExchangeResult<SharedBalance[]>(Exchange, SupportedTradingModes, result.Data.Select(x => new SharedBalance(x.MarginAsset, x.WithdrawAvailable, x.MarginBalance)).ToArray());
}
else
{
var result = await Account.GetIsolatedMarginAccountInfoAsync(ct: ct).ConfigureAwait(false);
if (!result)
return result.AsExchangeResult<SharedBalance[]>(Exchange, null, default);

return result.AsExchangeResult<SharedBalance[]>(Exchange, SupportedTradingModes, result.Data.Select(x => new SharedBalance(x.MarginAsset, x.MarginBalance, x.MarginFrozen + x.MarginBalance)
return result.AsExchangeResult<SharedBalance[]>(Exchange, SupportedTradingModes, result.Data.Select(x => new SharedBalance("USDT", x.WithdrawAvailable, x.MarginBalance)
{
IsolatedMarginSymbol = x.ContractCode
}).ToArray());
Expand Down Expand Up @@ -177,7 +177,44 @@ async Task<ExchangeWebResult<SharedFuturesSymbol[]>> IFuturesSymbolRestClient.Ge
ExchangeSymbolCache.UpdateSymbolInfo(_topicId, response.Data);
return response;
}
async Task<ExchangeResult<SharedSymbol[]>> IFuturesSymbolRestClient.GetFuturesSymbolsForBaseAssetAsync(string baseAsset)
{
if (!ExchangeSymbolCache.HasCached(_topicId))
{
var symbols = await ((IFuturesSymbolRestClient)this).GetFuturesSymbolsAsync(new GetSymbolsRequest()).ConfigureAwait(false);
if (!symbols)
return new ExchangeResult<SharedSymbol[]>(Exchange, symbols.Error!);
}

return new ExchangeResult<SharedSymbol[]>(Exchange, ExchangeSymbolCache.GetSymbolsForBaseAsset(_topicId, baseAsset));
}

async Task<ExchangeResult<bool>> IFuturesSymbolRestClient.SupportsFuturesSymbolAsync(SharedSymbol symbol)
{
if (symbol.TradingMode == TradingMode.Spot)
throw new ArgumentException(nameof(symbol), "Spot symbols not allowed");

if (!ExchangeSymbolCache.HasCached(_topicId))
{
var symbols = await ((IFuturesSymbolRestClient)this).GetFuturesSymbolsAsync(new GetSymbolsRequest()).ConfigureAwait(false);
if (!symbols)
return new ExchangeResult<bool>(Exchange, symbols.Error!);
}

return new ExchangeResult<bool>(Exchange, ExchangeSymbolCache.SupportsSymbol(_topicId, symbol));
}

async Task<ExchangeResult<bool>> IFuturesSymbolRestClient.SupportsFuturesSymbolAsync(string symbolName)
{
if (!ExchangeSymbolCache.HasCached(_topicId))
{
var symbols = await ((IFuturesSymbolRestClient)this).GetFuturesSymbolsAsync(new GetSymbolsRequest()).ConfigureAwait(false);
if (!symbols)
return new ExchangeResult<bool>(Exchange, symbols.Error!);
}

return new ExchangeResult<bool>(Exchange, ExchangeSymbolCache.SupportsSymbol(_topicId, symbolName));
}
#endregion

#region Futures Order Client
Expand Down Expand Up @@ -743,6 +780,7 @@ async Task<ExchangeWebResult<SharedPosition[]>> IFuturesOrderRestClient.GetPosit
UnrealizedPnl = x.UnrealizedPnl,
AverageOpenPrice = x.CostOpen,
Leverage = x.LeverageRate,
PositionMode = x.PositionMode == PositionMode.SingleSide ? SharedPositionMode.OneWay : SharedPositionMode.HedgeMode,
PositionSide = x.Side == OrderSide.Sell ? SharedPositionSide.Short : SharedPositionSide.Long
}).ToArray());
}
Expand All @@ -757,6 +795,7 @@ async Task<ExchangeWebResult<SharedPosition[]>> IFuturesOrderRestClient.GetPosit
UnrealizedPnl = x.UnrealizedPnl,
AverageOpenPrice = x.CostOpen,
Leverage = x.LeverageRate,
PositionMode = x.PositionMode == PositionMode.SingleSide ? SharedPositionMode.OneWay : SharedPositionMode.HedgeMode,
PositionSide = x.Side == OrderSide.Sell ? SharedPositionSide.Short : SharedPositionSide.Long
}).ToArray());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,15 +131,15 @@ async Task<ExchangeResult<UpdateSubscription>> IBalanceSocketClient.SubscribeToB
if (marginMode == SharedMarginMode.Cross)
{
var result = await SubscribeToCrossMarginBalanceUpdatesAsync(
update => handler(update.ToType<SharedBalance[]>(update.Data.Data.Select(x => new SharedBalance(x.MarginAsset, x.MarginBalance - x.MarginFrozen, x.MarginBalance) ).ToArray())),
update => handler(update.ToType<SharedBalance[]>(update.Data.Data.Select(x => new SharedBalance(x.MarginAsset, x.WithdrawAvailable, x.MarginBalance) ).ToArray())),
ct: ct).ConfigureAwait(false);

return new ExchangeResult<UpdateSubscription>(Exchange, result);
}
else
{
var result = await SubscribeToIsolatedMarginBalanceUpdatesAsync(
update => handler(update.ToType<SharedBalance[]>(update.Data.Data.Select(x => new SharedBalance(x.Asset, x.MarginBalance - x.MarginFrozen, x.MarginBalance) { IsolatedMarginSymbol = x.MarginAccount }).ToArray())),
update => handler(update.ToType<SharedBalance[]>(update.Data.Data.Select(x => new SharedBalance("USDT", x.WithdrawAvailable, x.MarginBalance) { IsolatedMarginSymbol = x.MarginAccount }).ToArray())),
ct: ct).ConfigureAwait(false);

return new ExchangeResult<UpdateSubscription>(Exchange, result);
Expand Down Expand Up @@ -326,6 +326,7 @@ async Task<ExchangeResult<UpdateSubscription>> IPositionSocketClient.SubscribeTo
ExchangeSymbolCache.ParseSymbol(_topicId, x.ContractCode), x.ContractCode, x.Quantity, update.Data.Timestamp)
{
AverageOpenPrice = x.PositionPrice,
PositionMode = x.PositionMode == PositionMode.SingleSide ? SharedPositionMode.OneWay : SharedPositionMode.HedgeMode,
PositionSide = x.OrderSide == Enums.OrderSide.Sell ? SharedPositionSide.Short : SharedPositionSide.Long,
Leverage = x.LeverageRate,
UnrealizedPnl = x.UnrealizedPnl
Expand All @@ -339,6 +340,7 @@ async Task<ExchangeResult<UpdateSubscription>> IPositionSocketClient.SubscribeTo
update => handler(update.ToType(update.Data.Data.Select(x => new SharedPosition(ExchangeSymbolCache.ParseSymbol(_topicId, x.ContractCode), x.ContractCode, x.Quantity, update.Data.Timestamp)
{
AverageOpenPrice = x.PositionPrice,
PositionMode = x.PositionMode == PositionMode.SingleSide ? SharedPositionMode.OneWay : SharedPositionMode.HedgeMode,
PositionSide = x.OrderSide == Enums.OrderSide.Sell ? SharedPositionSide.Short : SharedPositionSide.Long,
Leverage = x.LeverageRate,
UnrealizedPnl = x.UnrealizedPnl
Expand Down
7 changes: 6 additions & 1 deletion HTX.Net/Enums/EventTrigger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ public enum EventTrigger
/// Snapshot
/// </summary>
[Map("snapshot")]
Snapshot
Snapshot,
/// <summary>
/// Close order
/// </summary>
[Map("order.close")]
Close
}
}
4 changes: 2 additions & 2 deletions HTX.Net/HTX.Net.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net8.0;net9.0;net10.0;netstandard2.0;netstandard2.1</TargetFrameworks>
<Nullable>enable</Nullable>
Expand Down Expand Up @@ -52,7 +52,7 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="CryptoExchange.Net" Version="10.3.0" />
<PackageReference Include="CryptoExchange.Net" Version="10.4.0" />
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="10.0.101">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
Expand Down
68 changes: 68 additions & 0 deletions HTX.Net/HTX.Net.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6107,6 +6107,11 @@
Snapshot
</summary>
</member>
<member name="F:HTX.Net.Enums.EventTrigger.Close">
<summary>
Close order
</summary>
</member>
<member name="T:HTX.Net.Enums.FeeDeductStatus">
<summary>
Fee deduction status.
Expand Down Expand Up @@ -8019,6 +8024,37 @@
<member name="M:HTX.Net.HTXTrackerFactory.CreateTradeTracker(CryptoExchange.Net.SharedApis.SharedSymbol,System.Nullable{System.Int32},System.Nullable{System.TimeSpan})">
<inheritdoc />
</member>
<member name="M:HTX.Net.HTXTrackerFactory.CreateUserSpotDataTracker(CryptoExchange.Net.Trackers.UserData.Objects.SpotUserDataTrackerConfig)">
<inheritdoc />
</member>
<member name="M:HTX.Net.HTXTrackerFactory.CreateUserSpotDataTracker(System.String,CryptoExchange.Net.Authentication.ApiCredentials,CryptoExchange.Net.Trackers.UserData.Objects.SpotUserDataTrackerConfig,HTX.Net.HTXEnvironment)">
<inheritdoc />
</member>
<member name="M:HTX.Net.HTXTrackerFactory.CreateUserFuturesDataTracker(CryptoExchange.Net.SharedApis.SharedMarginMode,CryptoExchange.Net.Trackers.UserData.Objects.FuturesUserDataTrackerConfig)">
<inheritdoc />
</member>
<member name="M:HTX.Net.HTXTrackerFactory.CreateUserFuturesDataTracker(System.String,CryptoExchange.Net.Authentication.ApiCredentials,CryptoExchange.Net.SharedApis.SharedMarginMode,CryptoExchange.Net.Trackers.UserData.Objects.FuturesUserDataTrackerConfig,HTX.Net.HTXEnvironment)">
<inheritdoc />
</member>
<member name="T:HTX.Net.HTXUserSpotDataTracker">
<inheritdoc/>
</member>
<member name="M:HTX.Net.HTXUserSpotDataTracker.#ctor(Microsoft.Extensions.Logging.ILogger{HTX.Net.HTXUserSpotDataTracker},HTX.Net.Interfaces.Clients.IHTXRestClient,HTX.Net.Interfaces.Clients.IHTXSocketClient,System.String,CryptoExchange.Net.Trackers.UserData.Objects.SpotUserDataTrackerConfig)">
<summary>
ctor
</summary>
</member>
<member name="T:HTX.Net.HTXUserFuturesDataTracker">
<inheritdoc/>
</member>
<member name="P:HTX.Net.HTXUserFuturesDataTracker.WebsocketPositionUpdatesAreFullSnapshots">
<inheritdoc/>
</member>
<member name="M:HTX.Net.HTXUserFuturesDataTracker.#ctor(Microsoft.Extensions.Logging.ILogger{HTX.Net.HTXUserFuturesDataTracker},HTX.Net.Interfaces.Clients.IHTXRestClient,HTX.Net.Interfaces.Clients.IHTXSocketClient,System.String,CryptoExchange.Net.Trackers.UserData.Objects.FuturesUserDataTrackerConfig,CryptoExchange.Net.SharedApis.ExchangeParameters)">
<summary>
ctor
</summary>
</member>
<member name="T:HTX.Net.Interfaces.Clients.IHTXRestClient">
<summary>
Client for accessing the HTX API.
Expand Down Expand Up @@ -11258,6 +11294,38 @@
Tracker factory
</summary>
</member>
<member name="M:HTX.Net.Interfaces.IHTXTrackerFactory.CreateUserSpotDataTracker(System.String,CryptoExchange.Net.Authentication.ApiCredentials,CryptoExchange.Net.Trackers.UserData.Objects.SpotUserDataTrackerConfig,HTX.Net.HTXEnvironment)">
<summary>
Create a new Spot user data tracker
</summary>
<param name="userIdentifier">User identifier</param>
<param name="config">Configuration</param>
<param name="credentials">Credentials</param>
<param name="environment">Environment</param>
</member>
<member name="M:HTX.Net.Interfaces.IHTXTrackerFactory.CreateUserSpotDataTracker(CryptoExchange.Net.Trackers.UserData.Objects.SpotUserDataTrackerConfig)">
<summary>
Create a new spot user data tracker
</summary>
<param name="config">Configuration</param>
</member>
<member name="M:HTX.Net.Interfaces.IHTXTrackerFactory.CreateUserFuturesDataTracker(System.String,CryptoExchange.Net.Authentication.ApiCredentials,CryptoExchange.Net.SharedApis.SharedMarginMode,CryptoExchange.Net.Trackers.UserData.Objects.FuturesUserDataTrackerConfig,HTX.Net.HTXEnvironment)">
<summary>
Create a new futures user data tracker
</summary>
<param name="userIdentifier">User identifier</param>
<param name="config">Configuration</param>
<param name="credentials">Credentials</param>
<param name="marginMode">Margin mode</param>
<param name="environment">Environment</param>
</member>
<member name="M:HTX.Net.Interfaces.IHTXTrackerFactory.CreateUserFuturesDataTracker(CryptoExchange.Net.SharedApis.SharedMarginMode,CryptoExchange.Net.Trackers.UserData.Objects.FuturesUserDataTrackerConfig)">
<summary>
Create a new futures user data tracker
</summary>
<param name="config">Configuration</param>
<param name="marginMode">Margin mode</param>
</member>
<member name="T:HTX.Net.Objects.HTXApiAddresses">
<summary>
Api addresses usable for the HTX clients
Expand Down
Loading