diff --git a/HTX.Net/Clients/SpotApi/HTXRestClientSpotApiShared.cs b/HTX.Net/Clients/SpotApi/HTXRestClientSpotApiShared.cs index b7b11dc..fdc1a8a 100644 --- a/HTX.Net/Clients/SpotApi/HTXRestClientSpotApiShared.cs +++ b/HTX.Net/Clients/SpotApi/HTXRestClientSpotApiShared.cs @@ -72,6 +72,7 @@ async Task> IKlineRestClient.GetKlinesAsync(GetKlinesR #endregion #region Spot Symbol client + SharedSymbolCatalog? ISpotSymbolRestClient.SpotSymbolCatalog => ExchangeSymbolCache.GetSymbolCatalog(_exchangeName, _topicId, EnvironmentName, null); GetSpotSymbolsOptions ISpotSymbolRestClient.GetSpotSymbolsOptions { get; } = new GetSpotSymbolsOptions(_exchangeName, false); async Task> ISpotSymbolRestClient.GetSpotSymbolsAsync(GetSymbolsRequest request, CancellationToken ct) @@ -84,7 +85,17 @@ async Task> ISpotSymbolRestClient.GetSpotSymbolsA if (!result.Success) return HttpResult.Fail(result); - var response = HttpResult.Ok(result, result.Data.Select(s => new SharedSpotSymbol( + var data = result.Data + .Select(x => ParseSymbol(x)) + .ToArray(); + + ExchangeSymbolCache.UpdateSymbolInfo(_topicId, EnvironmentName, null, data); + return HttpResult.Ok(result, SharedUtils.ApplySymbolFilter(data, request)); + } + + private SharedSpotSymbol ParseSymbol(HTXSymbolConfig s) + { + var result = new SharedSpotSymbol( s.BaseAsset.ToUpperInvariant(), s.QuoteAsset.ToUpperInvariant(), s.Symbol, @@ -94,11 +105,27 @@ async Task> ISpotSymbolRestClient.GetSpotSymbolsA PriceDecimals = s.PricePrecision, MinNotionalValue = s.MinOrderValue, MinTradeQuantity = s.MinOrderQuantity, - MaxTradeQuantity = s.MaxOrderQuantity - }).ToArray()); + MaxTradeQuantity = s.MaxOrderQuantity, + DisplayName = s.Symbol, + QuoteAssetType = SharedAssetType.Crypto + }; + + if (LibraryHelpers.IsCommodity(s.BaseAsset)) + { + result.BaseAssetType = SharedAssetType.TradFi; + result.BaseAssetSubType = SharedAssetSubType.Commodity; + } + else + { + result.BaseAssetType = SharedAssetType.Crypto; + if (LibraryHelpers.IsStableCoin(s.BaseAsset)) + result.BaseAssetSubType = SharedAssetSubType.StableCoin; + } + + if (LibraryHelpers.IsStableCoin(s.QuoteAsset)) + result.QuoteAssetSubType = SharedAssetSubType.StableCoin; - ExchangeSymbolCache.UpdateSymbolInfo(_topicId, EnvironmentName, null, response.Data!); - return response; + return result; } async Task> ISpotSymbolRestClient.GetSpotSymbolsForBaseAssetAsync(string baseAsset) diff --git a/HTX.Net/Clients/UsdtFutures/HTXRestClientUsdtFuturesApiShared.cs b/HTX.Net/Clients/UsdtFutures/HTXRestClientUsdtFuturesApiShared.cs index ef9d066..90b4585 100644 --- a/HTX.Net/Clients/UsdtFutures/HTXRestClientUsdtFuturesApiShared.cs +++ b/HTX.Net/Clients/UsdtFutures/HTXRestClientUsdtFuturesApiShared.cs @@ -156,7 +156,8 @@ async Task> IBookTickerRestClient.GetBookTickerAsyn #endregion #region Futures Symbol client - +#warning Update to V5 + SharedSymbolCatalog? IFuturesSymbolRestClient.FuturesSymbolCatalog => ExchangeSymbolCache.GetSymbolCatalog(_exchangeName, _topicId, EnvironmentName, null); GetFuturesSymbolsOptions IFuturesSymbolRestClient.GetFuturesSymbolsOptions { get; } = new GetFuturesSymbolsOptions(_exchangeName, false); async Task> IFuturesSymbolRestClient.GetFuturesSymbolsAsync(GetSymbolsRequest request, CancellationToken ct) { @@ -168,26 +169,51 @@ async Task> IFuturesSymbolRestClient.GetFuture if (!result.Success) return HttpResult.Fail(result); - IEnumerable data = result.Data; - if (request.TradingMode.HasValue) - data = data.Where(x => request.TradingMode == TradingMode.PerpetualLinear ? x.BusinessType == BusinessType.Swap : x.BusinessType == BusinessType.Futures); + var data = result.Data + .Select(x => ParseSymbol(x)) + .ToArray(); + + ExchangeSymbolCache.UpdateSymbolInfo(_topicId, EnvironmentName, null, data); + return HttpResult.Ok(result, SharedUtils.ApplySymbolFilter(data, request)); + } - var response = HttpResult.Ok(result, data.Select(s => new SharedFuturesSymbol( + private SharedFuturesSymbol ParseSymbol(HTXContractInfo s) + { + var result = new SharedFuturesSymbol( s.BusinessType == BusinessType.Futures ? TradingMode.DeliveryLinear : TradingMode.PerpetualLinear, s.Asset, - "USDT", + "USDT", s.Symbol, s.Status == ContractStatus.Listing) { PriceStep = s.PriceTick, ContractSize = s.ContractSize, DeliveryTime = s.DeliveryDate, - QuantityStep = 1 - }).ToArray()); + QuantityStep = 1, + DisplayName = s.Symbol, + QuoteAssetType = SharedAssetType.Crypto, + QuoteAssetSubType = SharedAssetSubType.StableCoin + }; + + // HTX API has no way to retrieve underlying type specifics, we can only extract known types + if (LibraryHelpers.IsCommodity(result.BaseAsset)) + { + result.BaseAssetType = SharedAssetType.TradFi; + result.BaseAssetSubType = SharedAssetSubType.Commodity; + } + else if (LibraryHelpers.IsEquity(result.BaseAsset, ["X"], [])) + { + result.BaseAssetType = SharedAssetType.TradFi; + result.BaseAssetSubType = SharedAssetSubType.Equity; + } + else + { + result.BaseAssetType = SharedAssetType.Crypto; + } - ExchangeSymbolCache.UpdateSymbolInfo(_topicId, EnvironmentName, null, response.Data!); - return response; + return result; } + async Task> IFuturesSymbolRestClient.GetFuturesSymbolsForBaseAssetAsync(string baseAsset) { if (!ExchangeSymbolCache.HasCached(_topicId, EnvironmentName, null)) diff --git a/HTX.Net/HTX.Net.csproj b/HTX.Net/HTX.Net.csproj index 73c2f51..58f5af5 100644 --- a/HTX.Net/HTX.Net.csproj +++ b/HTX.Net/HTX.Net.csproj @@ -53,7 +53,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive