diff --git a/CryptoExchange.Net/CryptoExchange.Net.csproj b/CryptoExchange.Net/CryptoExchange.Net.csproj
index c22c03f..e5bb4b3 100644
--- a/CryptoExchange.Net/CryptoExchange.Net.csproj
+++ b/CryptoExchange.Net/CryptoExchange.Net.csproj
@@ -6,9 +6,9 @@
CryptoExchange.Net
JKorf
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.
- 10.3.0
- 10.3.0
- 10.3.0
+ 10.3.1
+ 10.3.1
+ 10.3.1
false
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
git
diff --git a/CryptoExchange.Net/ExchangeSymbolCache.cs b/CryptoExchange.Net/ExchangeSymbolCache.cs
index 2b237d4..da00729 100644
--- a/CryptoExchange.Net/ExchangeSymbolCache.cs
+++ b/CryptoExchange.Net/ExchangeSymbolCache.cs
@@ -32,6 +32,66 @@ namespace CryptoExchange.Net
_symbolInfos[topicId] = new ExchangeInfo(DateTime.UtcNow, updateData.ToDictionary(x => x.Name, x => x.SharedSymbol));
}
+ ///
+ /// Whether the specific topic has been cached
+ ///
+ /// Id
+ public static bool HasCached(string topicId)
+ {
+ if (!_symbolInfos.TryGetValue(topicId, out var exchangeInfo))
+ return false;
+
+ return exchangeInfo.Symbols.Count > 0;
+ }
+
+ ///
+ /// Whether a specific exchange(topic) support the provided symbol
+ ///
+ /// Id for the provided data
+ /// The symbol name
+ public static bool SupportsSymbol(string topicId, string symbolName)
+ {
+ if (!_symbolInfos.TryGetValue(topicId, out var exchangeInfo))
+ return false;
+
+ if (!exchangeInfo.Symbols.TryGetValue(symbolName, out var symbolInfo))
+ return false;
+
+ return true;
+ }
+
+ ///
+ /// Whether a specific exchange(topic) support the provided symbol
+ ///
+ /// Id for the provided data
+ /// The symbol info
+ public static bool SupportsSymbol(string topicId, SharedSymbol symbol)
+ {
+ if (!_symbolInfos.TryGetValue(topicId, out var exchangeInfo))
+ return false;
+
+ return exchangeInfo.Symbols.Any(x =>
+ x.Value.TradingMode == symbol.TradingMode
+ && x.Value.BaseAsset == symbol.BaseAsset
+ && x.Value.QuoteAsset == symbol.QuoteAsset);
+ }
+
+ ///
+ /// Get all symbols for a specific base asset
+ ///
+ /// Id for the provided data
+ /// Base asset name
+ public static SharedSymbol[] GetSymbolsForBaseAsset(string topicId, string baseAsset)
+ {
+ if (!_symbolInfos.TryGetValue(topicId, out var exchangeInfo))
+ return [];
+
+ return exchangeInfo.Symbols
+ .Where(x => x.Value.BaseAsset.Equals(baseAsset, StringComparison.InvariantCultureIgnoreCase))
+ .Select(x => x.Value)
+ .ToArray();
+ }
+
///
/// Parse a symbol name to a SharedSymbol
///
diff --git a/CryptoExchange.Net/SharedApis/Interfaces/Rest/Futures/IFuturesSymbolRestClient.cs b/CryptoExchange.Net/SharedApis/Interfaces/Rest/Futures/IFuturesSymbolRestClient.cs
index 81b27db..fa7e977 100644
--- a/CryptoExchange.Net/SharedApis/Interfaces/Rest/Futures/IFuturesSymbolRestClient.cs
+++ b/CryptoExchange.Net/SharedApis/Interfaces/Rest/Futures/IFuturesSymbolRestClient.cs
@@ -12,6 +12,25 @@ namespace CryptoExchange.Net.SharedApis
/// Futures symbol request options
///
EndpointOptions GetFuturesSymbolsOptions { get; }
+
+ ///
+ /// Get all futures symbols for a specific base asset
+ ///
+ /// Asset, for example `ETH`
+ Task> GetFuturesSymbolsForBaseAssetAsync(string baseAsset);
+
+ ///
+ /// Gets whether the client supports a futures symbol
+ ///
+ /// The symbol
+ Task> SupportsFuturesSymbolAsync(SharedSymbol symbol);
+
+ ///
+ /// Gets whether the client supports a futures symbol
+ ///
+ /// The symbol name
+ Task> SupportsFuturesSymbolAsync(string symbolName);
+
///
/// Get info on all futures symbols supported on the exchange
///
diff --git a/CryptoExchange.Net/SharedApis/Interfaces/Rest/Spot/ISpotSymbolRestClient.cs b/CryptoExchange.Net/SharedApis/Interfaces/Rest/Spot/ISpotSymbolRestClient.cs
index 78cb0f4..71f80a5 100644
--- a/CryptoExchange.Net/SharedApis/Interfaces/Rest/Spot/ISpotSymbolRestClient.cs
+++ b/CryptoExchange.Net/SharedApis/Interfaces/Rest/Spot/ISpotSymbolRestClient.cs
@@ -1,4 +1,5 @@
-using System.Threading;
+using CryptoExchange.Net.Objects;
+using System.Threading;
using System.Threading.Tasks;
namespace CryptoExchange.Net.SharedApis
@@ -13,6 +14,24 @@ namespace CryptoExchange.Net.SharedApis
///
EndpointOptions GetSpotSymbolsOptions { get; }
+ ///
+ /// Get all spot symbols for a specific base asset
+ ///
+ /// Asset, for example `ETH`
+ Task> GetSpotSymbolsForBaseAssetAsync(string baseAsset);
+
+ ///
+ /// Gets whether the client supports a spot symbol
+ ///
+ /// The symbol
+ Task> SupportsSpotSymbolAsync(SharedSymbol symbol);
+
+ ///
+ /// Gets whether the client supports a spot symbol
+ ///
+ /// The symbol name
+ Task> SupportsSpotSymbolAsync(string symbolName);
+
///
/// Get info on all available spot symbols on the exchange
///
diff --git a/CryptoExchange.Net/SharedApis/Models/ExchangeResult.cs b/CryptoExchange.Net/SharedApis/Models/ExchangeResult.cs
index be09d54..8532966 100644
--- a/CryptoExchange.Net/SharedApis/Models/ExchangeResult.cs
+++ b/CryptoExchange.Net/SharedApis/Models/ExchangeResult.cs
@@ -38,6 +38,17 @@ namespace CryptoExchange.Net.SharedApis
Exchange = exchange;
}
+ ///
+ /// ctor
+ ///
+ public ExchangeResult(
+ string exchange,
+ T result) :
+ base(result, null, null)
+ {
+ Exchange = exchange;
+ }
+
///
public override string ToString() => $"{Exchange} - " + base.ToString();
}
diff --git a/CryptoExchange.Net/Trackers/Klines/IKlineTracker.cs b/CryptoExchange.Net/Trackers/Klines/IKlineTracker.cs
index c83b54a..f18526b 100644
--- a/CryptoExchange.Net/Trackers/Klines/IKlineTracker.cs
+++ b/CryptoExchange.Net/Trackers/Klines/IKlineTracker.cs
@@ -55,6 +55,11 @@ namespace CryptoExchange.Net.Trackers.Klines
///
SharedKline? Last { get; }
+ ///
+ /// The kline interval
+ ///
+ public SharedKlineInterval Interval { get; }
+
///
/// Event for when a new kline is added
///
diff --git a/CryptoExchange.Net/Trackers/Klines/KlineTracker.cs b/CryptoExchange.Net/Trackers/Klines/KlineTracker.cs
index 3c475b5..5083474 100644
--- a/CryptoExchange.Net/Trackers/Klines/KlineTracker.cs
+++ b/CryptoExchange.Net/Trackers/Klines/KlineTracker.cs
@@ -45,10 +45,6 @@ namespace CryptoExchange.Net.Trackers.Klines
///
protected bool _changed = false;
///
- /// The kline interval
- ///
- protected readonly SharedKlineInterval _interval;
- ///
/// Whether the snapshot has been set
///
protected bool _snapshotSet;
@@ -66,6 +62,10 @@ namespace CryptoExchange.Net.Trackers.Klines
///
protected DateTime? _firstTimestamp;
+ ///
+ /// The kline interval
+ ///
+ public SharedKlineInterval Interval { get; }
///
public SyncStatus Status
{
@@ -165,7 +165,7 @@ namespace CryptoExchange.Net.Trackers.Klines
Exchange = restClient.Exchange;
Limit = limit;
Period = period;
- _interval = interval;
+ Interval = interval;
_socketClient = socketClient;
_restClient = restClient;
}
@@ -180,7 +180,7 @@ namespace CryptoExchange.Net.Trackers.Klines
Status = SyncStatus.Syncing;
_logger.KlineTrackerStarting(SymbolName);
- var subResult = await _socketClient.SubscribeToKlineUpdatesAsync(new SubscribeKlineRequest(Symbol, _interval),
+ var subResult = await _socketClient.SubscribeToKlineUpdatesAsync(new SubscribeKlineRequest(Symbol, Interval),
update =>
{
AddOrUpdate(update.Data);
@@ -237,7 +237,7 @@ namespace CryptoExchange.Net.Trackers.Klines
var limit = Math.Min(_restClient.GetKlinesOptions.MaxLimit, Limit ?? 100);
- var request = new GetKlinesRequest(Symbol, _interval, startTime, DateTime.UtcNow, limit: limit);
+ var request = new GetKlinesRequest(Symbol, Interval, startTime, DateTime.UtcNow, limit: limit);
var data = new List();
await foreach (var result in ExchangeHelpers.ExecutePages(_restClient.GetKlinesAsync, request).ConfigureAwait(false))
{
diff --git a/README.md b/README.md
index fc67e45..4e1656a 100644
--- a/README.md
+++ b/README.md
@@ -67,6 +67,9 @@ 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).
## Release notes
+* Version 10.3.1 - 27 Jan 2026
+ * Fixed potential collection modified exception upon logging message not handled in websocket message handling
+
* Version 10.3.0 - 22 Jan 2026
* Added PlatformInfo class for specifying platform metadata
* Added better handling for enabling AutoTimestamp in client options when not implemented in the API