diff --git a/CryptoExchange.Net/ExchangeSymbolCache.cs b/CryptoExchange.Net/ExchangeSymbolCache.cs new file mode 100644 index 0000000..b6b5cd3 --- /dev/null +++ b/CryptoExchange.Net/ExchangeSymbolCache.cs @@ -0,0 +1,67 @@ +using CryptoExchange.Net.SharedApis; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace CryptoExchange.Net +{ + /// + /// Cache for symbol parsing + /// + public static class ExchangeSymbolCache + { + private static ConcurrentDictionary _symbolInfos = new ConcurrentDictionary(); + + /// + /// Update the cached symbol data for an exchange + /// + /// Id for the provided data + /// Symbol data + public static void UpdateSymbolInfo(string topicId, SharedSpotSymbol[] updateData) + { + if(!_symbolInfos.TryGetValue(topicId, out var exchangeInfo)) + { + exchangeInfo = new ExchangeInfo(DateTime.UtcNow, updateData.ToDictionary(x => x.Name, x => new SharedSymbol(x.TradingMode, x.BaseAsset, x.QuoteAsset, (x as SharedFuturesSymbol)?.DeliveryTime) { SymbolName = x.Name })); + _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, x.QuoteAsset, (x as SharedFuturesSymbol)?.DeliveryTime) { SymbolName = x.Name })); + } + + /// + /// Parse a symbol name to a SharedSymbol + /// + /// Id for the provided data + /// Symbol name + public static SharedSymbol? ParseSymbol(string topicId, string symbolName) + { + if (!_symbolInfos.TryGetValue(topicId, out var exchangeInfo)) + return null; + + if (!exchangeInfo.Symbols.TryGetValue(symbolName, out var symbolInfo)) + return null; + + return new SharedSymbol(symbolInfo.TradingMode, symbolInfo.BaseAsset, symbolInfo.QuoteAsset, symbolName) + { + DeliverTime = symbolInfo.DeliverTime + }; + } + + class ExchangeInfo + { + public DateTime UpdateTime { get; set; } + public Dictionary Symbols { get; set; } + + public ExchangeInfo(DateTime updateTime, Dictionary symbols) + { + UpdateTime = updateTime; + Symbols = symbols; + } + } + } +} diff --git a/CryptoExchange.Net/SharedApis/Interfaces/ISharedClient.cs b/CryptoExchange.Net/SharedApis/Interfaces/ISharedClient.cs index fa1713e..eca53e9 100644 --- a/CryptoExchange.Net/SharedApis/Interfaces/ISharedClient.cs +++ b/CryptoExchange.Net/SharedApis/Interfaces/ISharedClient.cs @@ -33,19 +33,6 @@ namespace CryptoExchange.Net.SharedApis /// string FormatSymbol(string baseAsset, string quoteAsset, TradingMode tradingMode, DateTime? deliverDate = null); - /// - /// Parse a string to a shared symbol - /// - /// Symbol as returned by the server - /// Shared symbol - SharedSymbol ParseSymbol(string symbol); - - /// - /// Generate a new random client order id - /// - /// - string GenerateClientOrderId(); - /// /// Set a default exchange parameter. This can be used instead of passing in an ExchangeParameters object which each request. /// diff --git a/CryptoExchange.Net/SharedApis/ResponseModels/SharedBookTicker.cs b/CryptoExchange.Net/SharedApis/ResponseModels/SharedBookTicker.cs index fc3a454..7a67a10 100644 --- a/CryptoExchange.Net/SharedApis/ResponseModels/SharedBookTicker.cs +++ b/CryptoExchange.Net/SharedApis/ResponseModels/SharedBookTicker.cs @@ -3,7 +3,7 @@ /// /// Book ticker /// - public record SharedBookTicker + public record SharedBookTicker : SharedSymbolModel { /// /// Price of the best ask @@ -25,7 +25,8 @@ /// /// ctor /// - public SharedBookTicker(decimal bestAskPrice, decimal bestAskQuantity, decimal bestBidPrice, decimal bestBidQuantity) + public SharedBookTicker(SharedSymbol? sharedSymbol, string symbol, decimal bestAskPrice, decimal bestAskQuantity, decimal bestBidPrice, decimal bestBidQuantity) + : base(sharedSymbol, symbol) { BestAskPrice = bestAskPrice; BestAskQuantity = bestAskQuantity; diff --git a/CryptoExchange.Net/SharedApis/ResponseModels/SharedFuturesOrder.cs b/CryptoExchange.Net/SharedApis/ResponseModels/SharedFuturesOrder.cs index 3ad4dc1..a8a010b 100644 --- a/CryptoExchange.Net/SharedApis/ResponseModels/SharedFuturesOrder.cs +++ b/CryptoExchange.Net/SharedApis/ResponseModels/SharedFuturesOrder.cs @@ -5,12 +5,8 @@ namespace CryptoExchange.Net.SharedApis /// /// Futures order info /// - public record SharedFuturesOrder + public record SharedFuturesOrder : SharedSymbolModel { - /// - /// Symbol - /// - public string Symbol { get; set; } /// /// Id of the order /// @@ -97,14 +93,15 @@ namespace CryptoExchange.Net.SharedApis /// ctor /// public SharedFuturesOrder( + SharedSymbol? sharedSymbol, string symbol, string orderId, SharedOrderType orderType, SharedOrderSide orderSide, SharedOrderStatus orderStatus, DateTime? createTime) + : base(sharedSymbol, symbol) { - Symbol = symbol; OrderId = orderId; OrderType = orderType; Side = orderSide; diff --git a/CryptoExchange.Net/SharedApis/ResponseModels/SharedFuturesSymbol.cs b/CryptoExchange.Net/SharedApis/ResponseModels/SharedFuturesSymbol.cs index adc8c33..944bc6f 100644 --- a/CryptoExchange.Net/SharedApis/ResponseModels/SharedFuturesSymbol.cs +++ b/CryptoExchange.Net/SharedApis/ResponseModels/SharedFuturesSymbol.cs @@ -7,10 +7,6 @@ namespace CryptoExchange.Net.SharedApis /// public record SharedFuturesSymbol : SharedSpotSymbol { - /// - /// Symbol type - /// - public SharedSymbolType SymbolType { get; set; } /// /// The size of a single contract /// @@ -27,9 +23,8 @@ namespace CryptoExchange.Net.SharedApis /// /// ctor /// - public SharedFuturesSymbol(SharedSymbolType symbolType, string baseAsset, string quoteAsset, string symbol, bool trading) : base(baseAsset, quoteAsset, symbol, trading) + public SharedFuturesSymbol(TradingMode symbolType, string baseAsset, string quoteAsset, string symbol, bool trading) : base(baseAsset, quoteAsset, symbol, trading, symbolType) { - SymbolType = symbolType; } } } diff --git a/CryptoExchange.Net/SharedApis/ResponseModels/SharedFuturesTicker.cs b/CryptoExchange.Net/SharedApis/ResponseModels/SharedFuturesTicker.cs index 357b80c..cfd6915 100644 --- a/CryptoExchange.Net/SharedApis/ResponseModels/SharedFuturesTicker.cs +++ b/CryptoExchange.Net/SharedApis/ResponseModels/SharedFuturesTicker.cs @@ -5,12 +5,8 @@ namespace CryptoExchange.Net.SharedApis /// /// Futures ticker info /// - public record SharedFuturesTicker + public record SharedFuturesTicker: SharedSymbolModel { - /// - /// The symbol - /// - public string Symbol { get; set; } /// /// Last trade price /// @@ -51,9 +47,9 @@ namespace CryptoExchange.Net.SharedApis /// /// ctor /// - public SharedFuturesTicker(string symbol, decimal? lastPrice, decimal? highPrice, decimal? lowPrice, decimal volume, decimal? changePercentage) + public SharedFuturesTicker(SharedSymbol? sharedSymbol, string symbol, decimal? lastPrice, decimal? highPrice, decimal? lowPrice, decimal volume, decimal? changePercentage) + :base(sharedSymbol, symbol) { - Symbol = symbol; LastPrice = lastPrice; HighPrice = highPrice; LowPrice = lowPrice; diff --git a/CryptoExchange.Net/SharedApis/ResponseModels/SharedPosition.cs b/CryptoExchange.Net/SharedApis/ResponseModels/SharedPosition.cs index fac4dd0..78ae3db 100644 --- a/CryptoExchange.Net/SharedApis/ResponseModels/SharedPosition.cs +++ b/CryptoExchange.Net/SharedApis/ResponseModels/SharedPosition.cs @@ -5,12 +5,8 @@ namespace CryptoExchange.Net.SharedApis /// /// Position info /// - public record SharedPosition + public record SharedPosition : SharedSymbolModel { - /// - /// Symbol - /// - public string Symbol { get; set; } /// /// Current size of the position /// @@ -43,9 +39,9 @@ namespace CryptoExchange.Net.SharedApis /// /// ctor /// - public SharedPosition(string symbol, decimal positionSize, DateTime? updateTime) + public SharedPosition(SharedSymbol? sharedSymbol, string symbol, decimal positionSize, DateTime? updateTime) + : base(sharedSymbol, symbol) { - Symbol = symbol; PositionSize = positionSize; UpdateTime = updateTime; } diff --git a/CryptoExchange.Net/SharedApis/ResponseModels/SharedPositionHistory.cs b/CryptoExchange.Net/SharedApis/ResponseModels/SharedPositionHistory.cs index 42263a9..e4f1261 100644 --- a/CryptoExchange.Net/SharedApis/ResponseModels/SharedPositionHistory.cs +++ b/CryptoExchange.Net/SharedApis/ResponseModels/SharedPositionHistory.cs @@ -5,12 +5,8 @@ namespace CryptoExchange.Net.SharedApis /// /// Position history /// - public record SharedPositionHistory + public record SharedPositionHistory : SharedSymbolModel { - /// - /// Symbol of the position - /// - public string Symbol { get; set; } /// /// The side of the position /// @@ -52,6 +48,7 @@ namespace CryptoExchange.Net.SharedApis /// ctor /// public SharedPositionHistory( + SharedSymbol? sharedSymbol, string symbol, SharedPositionSide side, decimal openPrice, @@ -59,8 +56,8 @@ namespace CryptoExchange.Net.SharedApis decimal quantity, decimal realizedPnl, DateTime timestamp) + : base(sharedSymbol, symbol) { - Symbol = symbol; PositionSide = side; AverageOpenPrice = openPrice; AverageClosePrice = closePrice; diff --git a/CryptoExchange.Net/SharedApis/ResponseModels/SharedSpotOrder.cs b/CryptoExchange.Net/SharedApis/ResponseModels/SharedSpotOrder.cs index 2cb82b1..c2808e6 100644 --- a/CryptoExchange.Net/SharedApis/ResponseModels/SharedSpotOrder.cs +++ b/CryptoExchange.Net/SharedApis/ResponseModels/SharedSpotOrder.cs @@ -5,12 +5,8 @@ namespace CryptoExchange.Net.SharedApis /// /// Spot order info /// - public record SharedSpotOrder + public record SharedSpotOrder : SharedSymbolModel { - /// - /// The symbol the order is on - /// - public string Symbol { get; set; } /// /// The id of the order /// @@ -84,14 +80,15 @@ namespace CryptoExchange.Net.SharedApis /// ctor /// public SharedSpotOrder( + SharedSymbol? sharedSymbol, string symbol, string orderId, SharedOrderType orderType, SharedOrderSide orderSide, SharedOrderStatus orderStatus, DateTime? createTime) + : base(sharedSymbol, symbol) { - Symbol = symbol; OrderId = orderId; OrderType = orderType; Side = orderSide; diff --git a/CryptoExchange.Net/SharedApis/ResponseModels/SharedSpotSymbol.cs b/CryptoExchange.Net/SharedApis/ResponseModels/SharedSpotSymbol.cs index 818c012..71cd41d 100644 --- a/CryptoExchange.Net/SharedApis/ResponseModels/SharedSpotSymbol.cs +++ b/CryptoExchange.Net/SharedApis/ResponseModels/SharedSpotSymbol.cs @@ -5,6 +5,10 @@ /// public record SharedSpotSymbol { + /// + /// The trading mode of the symbol + /// + public TradingMode TradingMode { get; set; } /// /// Base asset of the symbol /// @@ -57,8 +61,9 @@ /// /// ctor /// - public SharedSpotSymbol(string baseAsset, string quoteAsset, string symbol, bool trading) + public SharedSpotSymbol(string baseAsset, string quoteAsset, string symbol, bool trading, TradingMode? tradingMode = null) { + TradingMode = tradingMode ?? TradingMode.Spot; BaseAsset = baseAsset; QuoteAsset = quoteAsset; Name = symbol; diff --git a/CryptoExchange.Net/SharedApis/ResponseModels/SharedSpotTicker.cs b/CryptoExchange.Net/SharedApis/ResponseModels/SharedSpotTicker.cs index fd641a4..0e680c3 100644 --- a/CryptoExchange.Net/SharedApis/ResponseModels/SharedSpotTicker.cs +++ b/CryptoExchange.Net/SharedApis/ResponseModels/SharedSpotTicker.cs @@ -3,12 +3,8 @@ /// /// Ticker info /// - public record SharedSpotTicker + public record SharedSpotTicker: SharedSymbolModel { - /// - /// Symbol name - /// - public string Symbol { get; set; } /// /// Last trade price /// @@ -33,9 +29,9 @@ /// /// ctor /// - public SharedSpotTicker(string symbol, decimal? lastPrice, decimal? highPrice, decimal? lowPrice, decimal volume, decimal? changePercentage) + public SharedSpotTicker(SharedSymbol? sharedSymbol, string symbol, decimal? lastPrice, decimal? highPrice, decimal? lowPrice, decimal volume, decimal? changePercentage) + : base(sharedSymbol, symbol) { - Symbol = symbol; LastPrice = lastPrice; HighPrice = highPrice; LowPrice = lowPrice; diff --git a/CryptoExchange.Net/SharedApis/ResponseModels/SharedSymbolModel.cs b/CryptoExchange.Net/SharedApis/ResponseModels/SharedSymbolModel.cs new file mode 100644 index 0000000..d15849f --- /dev/null +++ b/CryptoExchange.Net/SharedApis/ResponseModels/SharedSymbolModel.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace CryptoExchange.Net.SharedApis +{ + /// + /// Symbol model + /// + public record SharedSymbolModel + { + /// + /// SharedSymbol, only filled when the related GetSpotSymbolsAsync or GetFuturesSymbolsAsync method has been called previously + /// + public SharedSymbol? SharedSymbol { get; set; } + /// + /// Symbol name + /// + public string Symbol { get; set; } + + /// + /// ctor + /// + public SharedSymbolModel(SharedSymbol? sharedSymbol, string symbol) + { + Symbol = symbol; + SharedSymbol = sharedSymbol; + } + } +} diff --git a/CryptoExchange.Net/SharedApis/ResponseModels/SharedUserTrade.cs b/CryptoExchange.Net/SharedApis/ResponseModels/SharedUserTrade.cs index 37c2a1f..1791ce6 100644 --- a/CryptoExchange.Net/SharedApis/ResponseModels/SharedUserTrade.cs +++ b/CryptoExchange.Net/SharedApis/ResponseModels/SharedUserTrade.cs @@ -5,12 +5,8 @@ namespace CryptoExchange.Net.SharedApis /// /// A user trade /// - public record SharedUserTrade + public record SharedUserTrade : SharedSymbolModel { - /// - /// Symbol the trade was on - /// - public string Symbol { get; set; } /// /// The trade id /// @@ -51,7 +47,8 @@ namespace CryptoExchange.Net.SharedApis /// /// ctor /// - public SharedUserTrade(string symbol, string orderId, string id, SharedOrderSide? side, decimal quantity, decimal price, DateTime timestamp) + public SharedUserTrade(SharedSymbol? sharedSymbol, string symbol, string orderId, string id, SharedOrderSide? side, decimal quantity, decimal price, DateTime timestamp) + : base(sharedSymbol, symbol) { Symbol = symbol; OrderId = orderId;