diff --git a/CryptoExchange.Net/ExchangeSymbolCache.cs b/CryptoExchange.Net/ExchangeSymbolCache.cs
index 74c4dc1..765b1e1 100644
--- a/CryptoExchange.Net/ExchangeSymbolCache.cs
+++ b/CryptoExchange.Net/ExchangeSymbolCache.cs
@@ -23,14 +23,14 @@ namespace CryptoExchange.Net
{
if(!_symbolInfos.TryGetValue(topicId, out var exchangeInfo))
{
- exchangeInfo = new ExchangeInfo(DateTime.UtcNow, updateData.ToDictionary(x => x.Name, x => new SharedSymbol(x.TradingMode, x.BaseAsset.ToUpperInvariant(), x.QuoteAsset.ToUpperInvariant(), (x as SharedFuturesSymbol)?.DeliveryTime) { SymbolName = x.Name }));
+ exchangeInfo = new ExchangeInfo(DateTime.UtcNow, updateData.ToDictionary(x => x.Name, x => x.SharedSymbol));
_symbolInfos.TryAdd(topicId, exchangeInfo);
}
if (DateTime.UtcNow - exchangeInfo.UpdateTime < TimeSpan.FromMinutes(60))
return;
- _symbolInfos[topicId] = new ExchangeInfo(DateTime.UtcNow, updateData.ToDictionary(x => x.Name, x => new SharedSymbol(x.TradingMode, x.BaseAsset.ToUpperInvariant(), x.QuoteAsset.ToUpperInvariant(), (x as SharedFuturesSymbol)?.DeliveryTime) { SymbolName = x.Name }));
+ _symbolInfos[topicId] = new ExchangeInfo(DateTime.UtcNow, updateData.ToDictionary(x => x.Name, x => x.SharedSymbol));
}
///
diff --git a/CryptoExchange.Net/SharedApis/Models/Options/Endpoints/EndpointOptions.cs b/CryptoExchange.Net/SharedApis/Models/Options/Endpoints/EndpointOptions.cs
index 3bc4b4b..0113ac4 100644
--- a/CryptoExchange.Net/SharedApis/Models/Options/Endpoints/EndpointOptions.cs
+++ b/CryptoExchange.Net/SharedApis/Models/Options/Endpoints/EndpointOptions.cs
@@ -109,6 +109,15 @@ namespace CryptoExchange.Net.SharedApis
///
public List RequiredOptionalParameters { get; set; } = new List();
+ ///
+ /// Whether this accepts multiple symbols (Only applicable to request requiring symbol parameters)
+ ///
+ public bool SupportsMultipleSymbols { get; set; } = false;
+ ///
+ /// The max number of symbols which can be passed in a call (Only applicable to request requiring symbol parameters)
+ ///
+ public int? MaxSymbolCount { get; set; }
+
///
/// ctor
///
@@ -141,6 +150,19 @@ namespace CryptoExchange.Net.SharedApis
}
+ if (request is SharedSymbolRequest symbolsRequest)
+ {
+ if (symbolsRequest.Symbols != null)
+ {
+ if (!SupportsMultipleSymbols)
+ return new ArgumentError($"Only a single symbol parameter is allowed, multiple symbols are not supported");
+
+ if (symbolsRequest.Symbols.Length > MaxSymbolCount)
+ return new ArgumentError($"Max number of symbols is {MaxSymbolCount} but {symbolsRequest.Symbols.Length} were passed");
+ }
+
+ }
+
return ValidateRequest(exchange, request.ExchangeParameters, tradingMode, supportedTradingModes);
}
diff --git a/CryptoExchange.Net/SharedApis/Models/SharedSymbolRequest.cs b/CryptoExchange.Net/SharedApis/Models/SharedSymbolRequest.cs
index b022692..a50355c 100644
--- a/CryptoExchange.Net/SharedApis/Models/SharedSymbolRequest.cs
+++ b/CryptoExchange.Net/SharedApis/Models/SharedSymbolRequest.cs
@@ -1,14 +1,27 @@
-namespace CryptoExchange.Net.SharedApis
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace CryptoExchange.Net.SharedApis
{
///
/// Symbol request
///
public record SharedSymbolRequest : SharedRequest
{
+ ///
+ /// Trading mode
+ ///
+ public TradingMode TradingMode { get; }
///
/// The symbol
///
- public SharedSymbol Symbol { get; set; }
+ public SharedSymbol? Symbol { get; set; }
+ ///
+ /// Symbols
+ ///
+ public SharedSymbol[]? Symbols { get; set; }
///
/// ctor
@@ -16,6 +29,22 @@
public SharedSymbolRequest(SharedSymbol symbol, ExchangeParameters? exchangeParameters = null) : base(exchangeParameters)
{
Symbol = symbol;
+ TradingMode = symbol.TradingMode;
+ }
+
+ ///
+ /// ctor
+ ///
+ public SharedSymbolRequest(IEnumerable symbols, ExchangeParameters? exchangeParameters = null) : base(exchangeParameters)
+ {
+ if (!symbols.Any())
+ throw new ArgumentException("Empty symbol list");
+
+ if (symbols.GroupBy(x => x.TradingMode).Count() > 1)
+ throw new ArgumentException("All symbols in the symbol list should have the same trading mode");
+
+ Symbols = symbols.ToArray();
+ TradingMode = Symbols.First().TradingMode;
}
}
}
diff --git a/CryptoExchange.Net/SharedApis/Models/Socket/SubscribeBookTickerRequest.cs b/CryptoExchange.Net/SharedApis/Models/Socket/SubscribeBookTickerRequest.cs
index 5cc5563..6cabc03 100644
--- a/CryptoExchange.Net/SharedApis/Models/Socket/SubscribeBookTickerRequest.cs
+++ b/CryptoExchange.Net/SharedApis/Models/Socket/SubscribeBookTickerRequest.cs
@@ -1,4 +1,6 @@
-namespace CryptoExchange.Net.SharedApis
+using System.Collections.Generic;
+
+namespace CryptoExchange.Net.SharedApis
{
///
/// Request to subscribe to book ticker updates
@@ -13,5 +15,22 @@
public SubscribeBookTickerRequest(SharedSymbol symbol, ExchangeParameters? exchangeParameters = null) : base(symbol, exchangeParameters)
{
}
+
+ ///
+ /// ctor
+ ///
+ /// The symbols to subscribe to
+ /// Exchange specific parameters
+ public SubscribeBookTickerRequest(IEnumerable symbols, ExchangeParameters? exchangeParameters = null) : base(symbols, exchangeParameters)
+ {
+ }
+
+ ///
+ /// ctor
+ ///
+ /// The symbols to subscribe to
+ public SubscribeBookTickerRequest(params SharedSymbol[] symbols) : base(symbols, null)
+ {
+ }
}
}
diff --git a/CryptoExchange.Net/SharedApis/Models/Socket/SubscribeKlineRequest.cs b/CryptoExchange.Net/SharedApis/Models/Socket/SubscribeKlineRequest.cs
index 315423f..04a6dbb 100644
--- a/CryptoExchange.Net/SharedApis/Models/Socket/SubscribeKlineRequest.cs
+++ b/CryptoExchange.Net/SharedApis/Models/Socket/SubscribeKlineRequest.cs
@@ -1,4 +1,6 @@
-namespace CryptoExchange.Net.SharedApis
+using System.Collections.Generic;
+
+namespace CryptoExchange.Net.SharedApis
{
///
/// Request to subscribe to kline/candlestick updates
@@ -20,5 +22,26 @@
{
Interval = interval;
}
+
+ ///
+ /// ctor
+ ///
+ /// The symbols to subscribe to
+ /// Kline interval
+ /// Exchange specific parameters
+ public SubscribeKlineRequest(IEnumerable symbols, SharedKlineInterval interval, ExchangeParameters? exchangeParameters = null) : base(symbols, exchangeParameters)
+ {
+ Interval = interval;
+ }
+
+ ///
+ /// ctor
+ ///
+ /// Kline interval
+ /// The symbols to subscribe to
+ public SubscribeKlineRequest(SharedKlineInterval interval, params SharedSymbol[] symbols) : base(symbols, null)
+ {
+ Interval = interval;
+ }
}
}
diff --git a/CryptoExchange.Net/SharedApis/Models/Socket/SubscribeOrderBookRequest.cs b/CryptoExchange.Net/SharedApis/Models/Socket/SubscribeOrderBookRequest.cs
index e88ae1d..65f744d 100644
--- a/CryptoExchange.Net/SharedApis/Models/Socket/SubscribeOrderBookRequest.cs
+++ b/CryptoExchange.Net/SharedApis/Models/Socket/SubscribeOrderBookRequest.cs
@@ -1,4 +1,6 @@
-namespace CryptoExchange.Net.SharedApis
+using System.Collections.Generic;
+
+namespace CryptoExchange.Net.SharedApis
{
///
/// Request to subscribe to order book snapshot updates
@@ -20,5 +22,22 @@
{
Limit = limit;
}
+
+ ///
+ /// ctor
+ ///
+ /// The symbols to subscribe to
+ /// Exchange specific parameters
+ public SubscribeOrderBookRequest(IEnumerable symbols, ExchangeParameters? exchangeParameters = null) : base(symbols, exchangeParameters)
+ {
+ }
+
+ ///
+ /// ctor
+ ///
+ /// The symbols to subscribe to
+ public SubscribeOrderBookRequest(params SharedSymbol[] symbols) : base(symbols, null)
+ {
+ }
}
}
diff --git a/CryptoExchange.Net/SharedApis/Models/Socket/SubscribeTickerRequest.cs b/CryptoExchange.Net/SharedApis/Models/Socket/SubscribeTickerRequest.cs
index 5eef7ae..46f3636 100644
--- a/CryptoExchange.Net/SharedApis/Models/Socket/SubscribeTickerRequest.cs
+++ b/CryptoExchange.Net/SharedApis/Models/Socket/SubscribeTickerRequest.cs
@@ -1,4 +1,7 @@
-namespace CryptoExchange.Net.SharedApis
+using System.Collections;
+using System.Collections.Generic;
+
+namespace CryptoExchange.Net.SharedApis
{
///
/// Request to subscribe to ticker updates
@@ -13,5 +16,22 @@
public SubscribeTickerRequest(SharedSymbol symbol, ExchangeParameters? exchangeParameters = null) : base(symbol, exchangeParameters)
{
}
+
+ ///
+ /// ctor
+ ///
+ /// The symbols to subscribe to
+ /// Exchange specific parameters
+ public SubscribeTickerRequest(IEnumerable symbols, ExchangeParameters? exchangeParameters = null) : base(symbols, exchangeParameters)
+ {
+ }
+
+ ///
+ /// ctor
+ ///
+ /// The symbols to subscribe to
+ public SubscribeTickerRequest(params SharedSymbol[] symbols) : base(symbols, null)
+ {
+ }
}
}
diff --git a/CryptoExchange.Net/SharedApis/Models/Socket/SubscribeTradeRequest.cs b/CryptoExchange.Net/SharedApis/Models/Socket/SubscribeTradeRequest.cs
index d416075..115cc1f 100644
--- a/CryptoExchange.Net/SharedApis/Models/Socket/SubscribeTradeRequest.cs
+++ b/CryptoExchange.Net/SharedApis/Models/Socket/SubscribeTradeRequest.cs
@@ -1,4 +1,6 @@
-namespace CryptoExchange.Net.SharedApis
+using System.Collections.Generic;
+
+namespace CryptoExchange.Net.SharedApis
{
///
/// Request to subscribe to trade updates
@@ -13,5 +15,22 @@
public SubscribeTradeRequest(SharedSymbol symbol, ExchangeParameters? exchangeParameters = null) : base(symbol, exchangeParameters)
{
}
+
+ ///
+ /// ctor
+ ///
+ /// The symbols to subscribe to
+ /// Exchange specific parameters
+ public SubscribeTradeRequest(IEnumerable symbols, ExchangeParameters? exchangeParameters = null) : base(symbols, exchangeParameters)
+ {
+ }
+
+ ///
+ /// ctor
+ ///
+ /// The symbols to subscribe to
+ public SubscribeTradeRequest(params SharedSymbol[] symbols) : base(symbols, null)
+ {
+ }
}
}
diff --git a/CryptoExchange.Net/SharedApis/ResponseModels/SharedFuturesSymbol.cs b/CryptoExchange.Net/SharedApis/ResponseModels/SharedFuturesSymbol.cs
index ed4e84e..7f24acd 100644
--- a/CryptoExchange.Net/SharedApis/ResponseModels/SharedFuturesSymbol.cs
+++ b/CryptoExchange.Net/SharedApis/ResponseModels/SharedFuturesSymbol.cs
@@ -30,5 +30,8 @@ namespace CryptoExchange.Net.SharedApis
public SharedFuturesSymbol(TradingMode symbolType, string baseAsset, string quoteAsset, string symbol, bool trading) : base(baseAsset, quoteAsset, symbol, trading, symbolType)
{
}
+
+ ///
+ public override SharedSymbol SharedSymbol => new SharedSymbol(TradingMode, BaseAsset.ToUpperInvariant(), QuoteAsset.ToUpperInvariant(), DeliveryTime) { SymbolName = Name };
}
}
diff --git a/CryptoExchange.Net/SharedApis/ResponseModels/SharedSpotSymbol.cs b/CryptoExchange.Net/SharedApis/ResponseModels/SharedSpotSymbol.cs
index 71cd41d..ef8a9bd 100644
--- a/CryptoExchange.Net/SharedApis/ResponseModels/SharedSpotSymbol.cs
+++ b/CryptoExchange.Net/SharedApis/ResponseModels/SharedSpotSymbol.cs
@@ -69,5 +69,11 @@
Name = symbol;
Trading = trading;
}
+
+ ///
+ /// The SharedSymbol of this symbol
+ ///
+ ///
+ public virtual SharedSymbol SharedSymbol => new SharedSymbol(TradingMode, BaseAsset.ToUpperInvariant(), QuoteAsset.ToUpperInvariant()) { SymbolName = Name };
}
}
diff --git a/CryptoExchange.Net/Sockets/SocketConnection.cs b/CryptoExchange.Net/Sockets/SocketConnection.cs
index 7abc49d..3dc3fee 100644
--- a/CryptoExchange.Net/Sockets/SocketConnection.cs
+++ b/CryptoExchange.Net/Sockets/SocketConnection.cs
@@ -864,7 +864,7 @@ namespace CryptoExchange.Net.Sockets
{
if (ApiClient.MessageSendSizeLimit != null && data.Length > ApiClient.MessageSendSizeLimit.Value)
{
- var info = $"Message to send exceeds the max server message size ({ApiClient.MessageSendSizeLimit.Value} bytes). Split the request into batches to keep below this limit";
+ var info = $"Message to send exceeds the max server message size ({data.Length} vs {ApiClient.MessageSendSizeLimit.Value} bytes). Split the request into batches to keep below this limit";
_logger.LogWarning("[Sckt {SocketId}] [Req {RequestId}] {Info}", SocketId, requestId, info);
return new CallResult(new InvalidOperationError(info));
}
@@ -899,7 +899,7 @@ namespace CryptoExchange.Net.Sockets
{
if (ApiClient.MessageSendSizeLimit != null && data.Length > ApiClient.MessageSendSizeLimit.Value)
{
- var info = $"Message to send exceeds the max server message size ({ApiClient.MessageSendSizeLimit.Value} bytes). Split the request into batches to keep below this limit";
+ var info = $"Message to send exceeds the max server message size ({data.Length} vs {ApiClient.MessageSendSizeLimit.Value} bytes). Split the request into batches to keep below this limit";
_logger.LogWarning("[Sckt {SocketId}] [Req {RequestId}] {Info}", SocketId, requestId, info);
return new CallResult(new InvalidOperationError(info));
}