From 1edf630f4e8ac7c20b52959cda7d45ed2307c335 Mon Sep 17 00:00:00 2001 From: Jkorf Date: Thu, 16 Jul 2026 14:29:45 +0200 Subject: [PATCH 1/4] wip --- .../CryptoComRestClientExchangeApiShared.cs | 115 ++++++++++++++++-- CryptoCom.Net/CryptoCom.Net.csproj | 4 +- .../Objects/Models/CryptoComSymbol.cs | 2 +- 3 files changed, 106 insertions(+), 15 deletions(-) diff --git a/CryptoCom.Net/Clients/ExchangeApi/CryptoComRestClientExchangeApiShared.cs b/CryptoCom.Net/Clients/ExchangeApi/CryptoComRestClientExchangeApiShared.cs index 6971711..3311501 100644 --- a/CryptoCom.Net/Clients/ExchangeApi/CryptoComRestClientExchangeApiShared.cs +++ b/CryptoCom.Net/Clients/ExchangeApi/CryptoComRestClientExchangeApiShared.cs @@ -26,6 +26,7 @@ internal partial class CryptoComRestClientExchangeApi : ICryptoComRestClientExch public void ResetDefaultExchangeParameters() => ExchangeParameters.ResetStaticParameters(); public SharedClientInfo Discover() => SharedUtils.GetClientInfo(CryptoComExchange.Metadata, this); + private readonly static HashSet _knownExchangeFiat = ["EUR", "USD", "BRL", "GBP", "CAD", "HKD", "KRW", "TWD", "RUB", "SGD"]; #region Asset client GetAssetsOptions IAssetsRestClient.GetAssetsOptions { get; } = new GetAssetsOptions(_exchangeName, true); @@ -388,6 +389,7 @@ async Task> IWithdrawRestClient.WithdrawAsync(WithdrawReque #endregion #region Spot Symbol client + SharedSymbolCatalog? ISpotSymbolRestClient.SpotSymbolCatalog => ExchangeSymbolCache.GetSymbolCatalog(_topicSpotId, EnvironmentName, null); GetSpotSymbolsOptions ISpotSymbolRestClient.GetSpotSymbolsOptions { get; } = new GetSpotSymbolsOptions(_exchangeName, false); async Task> ISpotSymbolRestClient.GetSpotSymbolsAsync(GetSymbolsRequest request, CancellationToken ct) @@ -400,18 +402,64 @@ async Task> ISpotSymbolRestClient.GetSpotSymbolsA if (!result.Success) return HttpResult.Fail(result); - var data = result.Data.Where(x => x.SymbolType == Enums.SymbolType.Spot); + var data = result.Data + .Where(x => x.SymbolType == Enums.SymbolType.Spot) + .Select(x => ParseSymbol(x)) + .ToArray(); - var response = HttpResult.Ok(result, data.Select(s => new SharedSpotSymbol(s.BaseAsset, s.QuoteAsset, s.Symbol, s.Tradable) + ExchangeSymbolCache.UpdateSymbolInfo(_topicSpotId, EnvironmentName, null, data); + return HttpResult.Ok(result, SharedUtils.ApplySymbolFilter(data, request)); + } + + private SharedSpotSymbol ParseSymbol(CryptoComSymbol s) + { + var result = new SharedSpotSymbol(s.BaseAsset, s.QuoteAsset, s.Symbol, s.Tradable) { QuantityStep = s.QuantityTickSize, PriceStep = s.PriceTickSize, PriceDecimals = s.PriceDecimals, QuantityDecimals = s.QuantityDecimals - }).ToArray()); + }; + + if (s.ProductType == ProductType.Equity) + { + result.BaseAssetType = SharedAssetType.TradFi; + result.BaseAssetSubType = SharedAssetSubType.Stock; + } + else if (s.ProductType == ProductType.Commodities) + { + result.BaseAssetType = SharedAssetType.TradFi; + result.BaseAssetSubType = SharedAssetSubType.Commodity; + } + else if (s.ProductType == ProductType.Currencies) + { + result.BaseAssetType = SharedAssetType.Fiat; + } + else if (s.ProductType == ProductType.EquityIndex) + { + result.BaseAssetType = SharedAssetType.TradFi; + result.BaseAssetSubType = SharedAssetSubType.Index; + } + else if (s.ProductType == ProductType.DigitalCurrencies) + { + result.BaseAssetType = SharedAssetType.Crypto; + if (LibraryHelpers.IsStableCoin(result.BaseAsset)) + result.BaseAssetSubType = SharedAssetSubType.StableCoin; + } + + if (_knownExchangeFiat.Contains(s.QuoteAsset)) + { + result.QuoteAssetType = SharedAssetType.Fiat; + } + else + { + result.QuoteAssetType = SharedAssetType.Crypto; + + if (LibraryHelpers.IsStableCoin(s.QuoteAsset)) + result.QuoteAssetSubType = SharedAssetSubType.StableCoin; + } - ExchangeSymbolCache.UpdateSymbolInfo(_topicSpotId, EnvironmentName, null, response.Data!); - return response; + return result; } async Task> ISpotSymbolRestClient.GetSpotSymbolsForBaseAssetAsync(string baseAsset) @@ -882,7 +930,7 @@ async Task> IFundingRateRestClient.GetFundingRat #endregion #region Futures Symbol client - + SharedSymbolCatalog? IFuturesSymbolRestClient.FuturesSymbolCatalog => ExchangeSymbolCache.GetSymbolCatalog(_topicFuturesId, EnvironmentName, null); GetFuturesSymbolsOptions IFuturesSymbolRestClient.GetFuturesSymbolsOptions { get; } = new GetFuturesSymbolsOptions(_exchangeName, false); async Task> IFuturesSymbolRestClient.GetFuturesSymbolsAsync(GetSymbolsRequest request, CancellationToken ct) { @@ -894,10 +942,18 @@ async Task> IFuturesSymbolRestClient.GetFuture if (!result.Success) return HttpResult.Fail(result); - var data = result.Data.Where(x => x.SymbolType != SymbolType.Spot && x.SymbolType != SymbolType.CroStake); - if (request.TradingMode != null) - data = data.Where(x => request.TradingMode == TradingMode.PerpetualLinear ? x.SymbolType == SymbolType.PerpetualSwap : x.SymbolType == SymbolType.DeliveryFuture); - var response = HttpResult.Ok(result, data.Select(s => new SharedFuturesSymbol( + var data = result.Data + .Where(x => x.SymbolType != SymbolType.Spot && x.SymbolType != SymbolType.CroStake) + .Select(x => ParseFuturesSymbol(x)) + .ToArray(); + + ExchangeSymbolCache.UpdateSymbolInfo(_topicSpotId, EnvironmentName, null, data); + return HttpResult.Ok(result, SharedUtils.ApplySymbolFilter(data, request)); + } + + private SharedFuturesSymbol ParseFuturesSymbol(CryptoComSymbol s) + { + var result = new SharedFuturesSymbol( s.SymbolType == SymbolType.PerpetualSwap ? TradingMode.PerpetualLinear : TradingMode.DeliveryLinear, s.BaseAsset, s.QuoteAsset, s.Symbol, s.Tradable) { QuantityStep = s.QuantityTickSize, @@ -908,10 +964,43 @@ async Task> IFuturesSymbolRestClient.GetFuture ContractSize = s.ContractSize > 0 ? s.ContractSize.Value : 1m, MaxLongLeverage = s.MaxLeverage, MaxShortLeverage = s.MaxLeverage - }).ToArray()); + }; + + if (s.ProductType == ProductType.Equity + || (s.ProductType == ProductType.EquityIndex)) // etfs + { + result.BaseAssetType = SharedAssetType.TradFi; + result.BaseAssetSubType = SharedAssetSubType.Stock; + } + else if (s.ProductType == ProductType.Commodities) + { + result.BaseAssetType = SharedAssetType.TradFi; + result.BaseAssetSubType = SharedAssetSubType.Commodity; + } + else if (s.ProductType == ProductType.Currencies) + { + result.BaseAssetType = SharedAssetType.Fiat; + } + else if (s.ProductType == ProductType.DigitalCurrencies) + { + result.BaseAssetType = SharedAssetType.Crypto; + if (LibraryHelpers.IsStableCoin(result.BaseAsset)) + result.BaseAssetSubType = SharedAssetSubType.StableCoin; + } + + if (_knownExchangeFiat.Contains(s.QuoteAsset)) + { + result.QuoteAssetType = SharedAssetType.Fiat; + } + else + { + result.QuoteAssetType = SharedAssetType.Crypto; + + if (LibraryHelpers.IsStableCoin(s.QuoteAsset)) + result.QuoteAssetSubType = SharedAssetSubType.StableCoin; + } - ExchangeSymbolCache.UpdateSymbolInfo(_topicFuturesId, EnvironmentName, null, response.Data!); - return response; + return result; } async Task> IFuturesSymbolRestClient.GetFuturesSymbolsForBaseAssetAsync(string baseAsset) diff --git a/CryptoCom.Net/CryptoCom.Net.csproj b/CryptoCom.Net/CryptoCom.Net.csproj index 1c783d6..48af85c 100644 --- a/CryptoCom.Net/CryptoCom.Net.csproj +++ b/CryptoCom.Net/CryptoCom.Net.csproj @@ -53,10 +53,12 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - all runtime; build; native; contentfiles; analyzers; buildtransitive + + + \ No newline at end of file diff --git a/CryptoCom.Net/Objects/Models/CryptoComSymbol.cs b/CryptoCom.Net/Objects/Models/CryptoComSymbol.cs index d3e1eaa..3de95ef 100644 --- a/CryptoCom.Net/Objects/Models/CryptoComSymbol.cs +++ b/CryptoCom.Net/Objects/Models/CryptoComSymbol.cs @@ -85,7 +85,7 @@ public record CryptoComSymbol /// ["expiry_timestamp_ms"] Expiry timestamp /// [JsonPropertyName("expiry_timestamp_ms")] - public DateTime ExpiryTime { get; set; } + public DateTime? ExpiryTime { get; set; } /// /// ["underlying_symbol"] Underlying symbol /// From 7a608bac9c7a80467a4300e4358060d2ef73cd6c Mon Sep 17 00:00:00 2001 From: Jkorf Date: Fri, 17 Jul 2026 16:31:44 +0200 Subject: [PATCH 2/4] wip --- .../CryptoComRestClientExchangeApiShared.cs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/CryptoCom.Net/Clients/ExchangeApi/CryptoComRestClientExchangeApiShared.cs b/CryptoCom.Net/Clients/ExchangeApi/CryptoComRestClientExchangeApiShared.cs index 3311501..989eee2 100644 --- a/CryptoCom.Net/Clients/ExchangeApi/CryptoComRestClientExchangeApiShared.cs +++ b/CryptoCom.Net/Clients/ExchangeApi/CryptoComRestClientExchangeApiShared.cs @@ -421,10 +421,11 @@ private SharedSpotSymbol ParseSymbol(CryptoComSymbol s) QuantityDecimals = s.QuantityDecimals }; - if (s.ProductType == ProductType.Equity) + if (s.ProductType == ProductType.Equity || + s.ProductType == ProductType.EquityIndex) { result.BaseAssetType = SharedAssetType.TradFi; - result.BaseAssetSubType = SharedAssetSubType.Stock; + result.BaseAssetSubType = SharedAssetSubType.Equity; } else if (s.ProductType == ProductType.Commodities) { @@ -435,11 +436,6 @@ private SharedSpotSymbol ParseSymbol(CryptoComSymbol s) { result.BaseAssetType = SharedAssetType.Fiat; } - else if (s.ProductType == ProductType.EquityIndex) - { - result.BaseAssetType = SharedAssetType.TradFi; - result.BaseAssetSubType = SharedAssetSubType.Index; - } else if (s.ProductType == ProductType.DigitalCurrencies) { result.BaseAssetType = SharedAssetType.Crypto; @@ -970,7 +966,7 @@ private SharedFuturesSymbol ParseFuturesSymbol(CryptoComSymbol s) || (s.ProductType == ProductType.EquityIndex)) // etfs { result.BaseAssetType = SharedAssetType.TradFi; - result.BaseAssetSubType = SharedAssetSubType.Stock; + result.BaseAssetSubType = SharedAssetSubType.Equity; } else if (s.ProductType == ProductType.Commodities) { From c7de62b6190844538636b106f578b37814440ec8 Mon Sep 17 00:00:00 2001 From: JKorf Date: Sun, 19 Jul 2026 20:30:40 +0200 Subject: [PATCH 3/4] wip --- .../ExchangeApi/CryptoComRestClientExchangeApiShared.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/CryptoCom.Net/Clients/ExchangeApi/CryptoComRestClientExchangeApiShared.cs b/CryptoCom.Net/Clients/ExchangeApi/CryptoComRestClientExchangeApiShared.cs index 989eee2..eac364e 100644 --- a/CryptoCom.Net/Clients/ExchangeApi/CryptoComRestClientExchangeApiShared.cs +++ b/CryptoCom.Net/Clients/ExchangeApi/CryptoComRestClientExchangeApiShared.cs @@ -418,7 +418,8 @@ private SharedSpotSymbol ParseSymbol(CryptoComSymbol s) QuantityStep = s.QuantityTickSize, PriceStep = s.PriceTickSize, PriceDecimals = s.PriceDecimals, - QuantityDecimals = s.QuantityDecimals + QuantityDecimals = s.QuantityDecimals, + DisplayName = s.DisplayName }; if (s.ProductType == ProductType.Equity || @@ -959,10 +960,12 @@ private SharedFuturesSymbol ParseFuturesSymbol(CryptoComSymbol s) DeliveryTime = s.ExpiryTime, ContractSize = s.ContractSize > 0 ? s.ContractSize.Value : 1m, MaxLongLeverage = s.MaxLeverage, - MaxShortLeverage = s.MaxLeverage + MaxShortLeverage = s.MaxLeverage, + DisplayName = s.DisplayName }; if (s.ProductType == ProductType.Equity + || (s.ProductType == ProductType.PreIpo) // pre-ipo || (s.ProductType == ProductType.EquityIndex)) // etfs { result.BaseAssetType = SharedAssetType.TradFi; From dd4f877f5d4a4a111cdb85fe26d58a1a385b25b9 Mon Sep 17 00:00:00 2001 From: Jkorf Date: Mon, 20 Jul 2026 14:24:45 +0200 Subject: [PATCH 4/4] wip --- .../ExchangeApi/CryptoComRestClientExchangeApiShared.cs | 6 +++--- CryptoCom.Net/CryptoCom.Net.csproj | 4 +--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/CryptoCom.Net/Clients/ExchangeApi/CryptoComRestClientExchangeApiShared.cs b/CryptoCom.Net/Clients/ExchangeApi/CryptoComRestClientExchangeApiShared.cs index eac364e..b83886e 100644 --- a/CryptoCom.Net/Clients/ExchangeApi/CryptoComRestClientExchangeApiShared.cs +++ b/CryptoCom.Net/Clients/ExchangeApi/CryptoComRestClientExchangeApiShared.cs @@ -389,7 +389,7 @@ async Task> IWithdrawRestClient.WithdrawAsync(WithdrawReque #endregion #region Spot Symbol client - SharedSymbolCatalog? ISpotSymbolRestClient.SpotSymbolCatalog => ExchangeSymbolCache.GetSymbolCatalog(_topicSpotId, EnvironmentName, null); + SharedSymbolCatalog? ISpotSymbolRestClient.SpotSymbolCatalog => ExchangeSymbolCache.GetSymbolCatalog(_exchangeName, _topicSpotId, EnvironmentName, null); GetSpotSymbolsOptions ISpotSymbolRestClient.GetSpotSymbolsOptions { get; } = new GetSpotSymbolsOptions(_exchangeName, false); async Task> ISpotSymbolRestClient.GetSpotSymbolsAsync(GetSymbolsRequest request, CancellationToken ct) @@ -927,7 +927,7 @@ async Task> IFundingRateRestClient.GetFundingRat #endregion #region Futures Symbol client - SharedSymbolCatalog? IFuturesSymbolRestClient.FuturesSymbolCatalog => ExchangeSymbolCache.GetSymbolCatalog(_topicFuturesId, EnvironmentName, null); + SharedSymbolCatalog? IFuturesSymbolRestClient.FuturesSymbolCatalog => ExchangeSymbolCache.GetSymbolCatalog(_exchangeName, _topicFuturesId, EnvironmentName, null); GetFuturesSymbolsOptions IFuturesSymbolRestClient.GetFuturesSymbolsOptions { get; } = new GetFuturesSymbolsOptions(_exchangeName, false); async Task> IFuturesSymbolRestClient.GetFuturesSymbolsAsync(GetSymbolsRequest request, CancellationToken ct) { @@ -944,7 +944,7 @@ async Task> IFuturesSymbolRestClient.GetFuture .Select(x => ParseFuturesSymbol(x)) .ToArray(); - ExchangeSymbolCache.UpdateSymbolInfo(_topicSpotId, EnvironmentName, null, data); + ExchangeSymbolCache.UpdateSymbolInfo(_topicFuturesId, EnvironmentName, null, data); return HttpResult.Ok(result, SharedUtils.ApplySymbolFilter(data, request)); } diff --git a/CryptoCom.Net/CryptoCom.Net.csproj b/CryptoCom.Net/CryptoCom.Net.csproj index 48af85c..14419c7 100644 --- a/CryptoCom.Net/CryptoCom.Net.csproj +++ b/CryptoCom.Net/CryptoCom.Net.csproj @@ -53,12 +53,10 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - \ No newline at end of file