From 2cddfa79c51b5c99055b62601676d72ff82ebaab Mon Sep 17 00:00:00 2001 From: "F.Buldo" Date: Wed, 17 Jan 2018 00:26:27 +0100 Subject: [PATCH 01/21] added exchangeInfo --- .../Binance.API.Csharp.Client.csproj | 1 + Binance.API.Csharp.Client/BinanceClient.cs | 17 ++++++++++++++--- Binance.API.Csharp.Client/Utils/EndPoints.cs | 2 +- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/Binance.API.Csharp.Client/Binance.API.Csharp.Client.csproj b/Binance.API.Csharp.Client/Binance.API.Csharp.Client.csproj index d0d89bd..4088a05 100644 --- a/Binance.API.Csharp.Client/Binance.API.Csharp.Client.csproj +++ b/Binance.API.Csharp.Client/Binance.API.Csharp.Client.csproj @@ -72,5 +72,6 @@ Binance.API.Csharp.Client.Models + \ No newline at end of file diff --git a/Binance.API.Csharp.Client/BinanceClient.cs b/Binance.API.Csharp.Client/BinanceClient.cs index fd65700..906514f 100644 --- a/Binance.API.Csharp.Client/BinanceClient.cs +++ b/Binance.API.Csharp.Client/BinanceClient.cs @@ -88,11 +88,22 @@ private void ValidateOrderValue(string symbol, OrderType orderType, decimal unit } } - private void LoadTradingRules() + public void LoadTradingRules() { var apiClient = new ApiClient("", "", EndPoints.TradingRules, addDefaultHeaders: false); _tradingRules = apiClient.CallAsync(ApiMethod.GET, "").Result; } + + public async Task GetTradingRulesAsync() + { + if (_tradingRules != null) + return _tradingRules; + var result = await _apiClient.CallAsync(ApiMethod.GET, EndPoints.TradingRules, false); + + _tradingRules = result; + + return _tradingRules; + } #endregion #region General @@ -172,7 +183,7 @@ public async Task> GetCandleSticks(string symbol, TimeI } var args = $"symbol={symbol.ToUpper()}&interval={interval.GetDescription()}" - + (startTime .HasValue ? $"&startTime={startTime.Value.GetUnixTimeStamp()}" : "") + + (startTime.HasValue ? $"&startTime={startTime.Value.GetUnixTimeStamp()}" : "") + (endTime.HasValue ? $"&endTime={endTime.Value.GetUnixTimeStamp()}" : "") + $"&limit={limit}"; @@ -193,7 +204,7 @@ public async Task> GetPriceChange24H(string symbol { var args = string.IsNullOrWhiteSpace(symbol) ? "" : $"symbol={symbol.ToUpper()}"; - var result = await _apiClient.CallAsync>(ApiMethod.GET, EndPoints.TickerPriceChange24H, false, args); + var result = await _apiClient.CallAsync>(ApiMethod.GET, EndPoints.TickerPriceChange24H, false, args); return result; } diff --git a/Binance.API.Csharp.Client/Utils/EndPoints.cs b/Binance.API.Csharp.Client/Utils/EndPoints.cs index 681a066..75ef8b5 100644 --- a/Binance.API.Csharp.Client/Utils/EndPoints.cs +++ b/Binance.API.Csharp.Client/Utils/EndPoints.cs @@ -17,7 +17,7 @@ public static class EndPoints public static readonly string TickerPriceChange24H = "/api/v1/ticker/24hr"; public static readonly string AllPrices = "/api/v1/ticker/allPrices"; public static readonly string OrderBookTicker = "/api/v1/ticker/allBookTickers"; - public static readonly string TradingRules = "https://gist.githubusercontent.com/Ninj0r/3029b9d635f8f81f5ffab9cc9df5cc61/raw/810530a2118e5d8cdcfcc4d220349976a0acf131/tradingRules_20171022.json"; + public static readonly string TradingRules = "/api/v1/exchangeInfo"; #endregion #region Account Endpoints From 5629f5ff91cd895fb6c6227ff321b79097b70d42 Mon Sep 17 00:00:00 2001 From: "F.Buldo" Date: Thu, 25 Jan 2018 00:51:58 +0100 Subject: [PATCH 02/21] Added support for Partial Book Depth Streams --- .../WebSocket/DepthMessage.cs | 6 +++++ Binance.API.Csharp.Client/ApiClient.cs | 11 ++++++-- Binance.API.Csharp.Client/BinanceClient.cs | 12 +++++++++ .../Utils/CustomParser.cs | 26 +++++++++++++++++++ 4 files changed, 53 insertions(+), 2 deletions(-) diff --git a/Binance.API.Csharp.Client.Models/WebSocket/DepthMessage.cs b/Binance.API.Csharp.Client.Models/WebSocket/DepthMessage.cs index 4598ad4..3f4c8a7 100644 --- a/Binance.API.Csharp.Client.Models/WebSocket/DepthMessage.cs +++ b/Binance.API.Csharp.Client.Models/WebSocket/DepthMessage.cs @@ -12,4 +12,10 @@ public class DepthMessage public IEnumerable Bids { get; set; } public IEnumerable Asks { get; set; } } + public class DepthPartialMessage + { + public int UpdateId { get; set; } + public IEnumerable Bids { get; set; } + public IEnumerable Asks { get; set; } + } } diff --git a/Binance.API.Csharp.Client/ApiClient.cs b/Binance.API.Csharp.Client/ApiClient.cs index 7601abe..8bf9dbe 100644 --- a/Binance.API.Csharp.Client/ApiClient.cs +++ b/Binance.API.Csharp.Client/ApiClient.cs @@ -105,12 +105,19 @@ public void ConnectToWebSocket(string parameters, MessageHandler messageHa ws.OnMessage += (sender, e) => { - dynamic eventData; + dynamic eventData = null; if (useCustomParser) { var customParser = new CustomParser(); - eventData = customParser.GetParsedDepthMessage(JsonConvert.DeserializeObject(e.Data)); + var datum = JsonConvert.DeserializeObject(e.Data); + if (datum is JObject jobj) + { + if (datum["lastUpdateId"] != null) + eventData = customParser.GetParsedDepthPartialMessage(datum); + else + eventData = customParser.GetParsedDepthMessage(datum); + } } else { diff --git a/Binance.API.Csharp.Client/BinanceClient.cs b/Binance.API.Csharp.Client/BinanceClient.cs index d1c1a93..78fb132 100644 --- a/Binance.API.Csharp.Client/BinanceClient.cs +++ b/Binance.API.Csharp.Client/BinanceClient.cs @@ -585,6 +585,18 @@ public void ListenDepthEndpoint(string symbol, ApiClientAbstract.MessageHandler< _apiClient.ConnectToWebSocket(param, depthHandler, true); } + public void ListenPartialDepthEndPoint(string symbol,int levels, ApiClientAbstract.MessageHandler depthHandler) + { + if (string.IsNullOrWhiteSpace(symbol)) + { + throw new ArgumentException("symbol cannot be empty. ", "symbol"); + } + if (levels != 5 && levels != 10 && levels != 20) + throw new ArgumentException("Valid values for level are 5,10 or 20"); + var param = symbol.ToLower() + "@depth" + levels; + _apiClient.ConnectToWebSocket(param, depthHandler, true); + } + /// /// Listen to the Kline endpoint. /// diff --git a/Binance.API.Csharp.Client/Utils/CustomParser.cs b/Binance.API.Csharp.Client/Utils/CustomParser.cs index fb96404..561a8df 100644 --- a/Binance.API.Csharp.Client/Utils/CustomParser.cs +++ b/Binance.API.Csharp.Client/Utils/CustomParser.cs @@ -100,5 +100,31 @@ public DepthMessage GetParsedDepthMessage(dynamic messageData) return result; } + + public DepthPartialMessage GetParsedDepthPartialMessage(dynamic messageData) + { + var result = new DepthPartialMessage + { + UpdateId = messageData.lastUpdateId + }; + + var bids = new List(); + var asks = new List(); + + foreach (JToken item in ((JArray)messageData.bids).ToArray()) + { + bids.Add(new OrderBookOffer() { Price = decimal.Parse(item[0].ToString()), Quantity = decimal.Parse(item[1].ToString()) }); + } + + foreach (JToken item in ((JArray)messageData.asks).ToArray()) + { + asks.Add(new OrderBookOffer() { Price = decimal.Parse(item[0].ToString()), Quantity = decimal.Parse(item[1].ToString()) }); + } + + result.Bids = bids; + result.Asks = asks; + + return result; + } } } From 671617ee2b9826f933f7b93c47fd466fbc802525 Mon Sep 17 00:00:00 2001 From: "F.Buldo" Date: Thu, 25 Jan 2018 23:50:13 +0100 Subject: [PATCH 03/21] fix AccountUpdatedMessage --- .../WebSocket/AccountUpdatedMessage.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Binance.API.Csharp.Client.Models/WebSocket/AccountUpdatedMessage.cs b/Binance.API.Csharp.Client.Models/WebSocket/AccountUpdatedMessage.cs index ba0997b..1b7d0fc 100644 --- a/Binance.API.Csharp.Client.Models/WebSocket/AccountUpdatedMessage.cs +++ b/Binance.API.Csharp.Client.Models/WebSocket/AccountUpdatedMessage.cs @@ -17,12 +17,14 @@ public class AccountUpdatedMessage public int BuyerCommission { get; set; } [JsonProperty("s")] public int SellerCommission { get; set; } - [JsonProperty("t")] + [JsonProperty("T")] public bool CanTrade { get; set; } - [JsonProperty("w")] + [JsonProperty("W")] public bool CanWithdraw { get; set; } - [JsonProperty("d")] + [JsonProperty("D")] public bool CanDeposit { get; set; } + [JsonProperty("u")] + public long TimeLastAccountUpdate { get; set; } [JsonProperty("B")] public IEnumerable Balances { get; set; } } From 560a0b74af925de8c96759a9e8285f5de79d16b3 Mon Sep 17 00:00:00 2001 From: "F.Buldo" Date: Thu, 25 Jan 2018 23:51:01 +0100 Subject: [PATCH 04/21] fix userstreams --- Binance.API.Csharp.Client/ApiClient.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Binance.API.Csharp.Client/ApiClient.cs b/Binance.API.Csharp.Client/ApiClient.cs index 8bf9dbe..19a0712 100644 --- a/Binance.API.Csharp.Client/ApiClient.cs +++ b/Binance.API.Csharp.Client/ApiClient.cs @@ -42,7 +42,7 @@ public async Task CallAsync(ApiMethod method, string endpoint, bool isSign if (isSigned) { // Joining provided parameters - parameters += (!string.IsNullOrWhiteSpace(parameters) ? "×tamp=" : "timestamp=") + Utilities.GenerateTimeStamp(DateTime.Now.ToUniversalTime()); + parameters += (!string.IsNullOrWhiteSpace(parameters) ? "×tamp=" : "timestamp=") +( Utilities.GenerateTimeStamp(DateTime.Now.ToUniversalTime()) ); // Creating request signature var signature = Utilities.GenerateSignature(_apiSecret, parameters); @@ -85,8 +85,7 @@ public async Task CallAsync(ApiMethod method, string endpoint, bool isSign eMsg = i["msg"]?.Value(); } catch { } - } - + } throw new Exception(string.Format("Api Error Code: {0} Message: {1}", eCode, eMsg)); } @@ -158,7 +157,7 @@ public void ConnectToUserDataWebSocket(string parameters, MessageHandler(e.Data); - switch (eventData.e) + switch (eventData.e.Value) { case "outboundAccountInfo": accountHandler(JsonConvert.DeserializeObject(e.Data)); From a187e171985963d2e4a9ac287e2c7d4ab6b95795 Mon Sep 17 00:00:00 2001 From: "F.Buldo" Date: Thu, 25 Jan 2018 23:52:06 +0100 Subject: [PATCH 05/21] add DeltaTimeAdjustment to solve server time synchronization problems ( local time ahead of server time ) --- Binance.API.Csharp.Client/Utils/Utilities.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Binance.API.Csharp.Client/Utils/Utilities.cs b/Binance.API.Csharp.Client/Utils/Utilities.cs index ef4159a..c56ff64 100644 --- a/Binance.API.Csharp.Client/Utils/Utilities.cs +++ b/Binance.API.Csharp.Client/Utils/Utilities.cs @@ -10,6 +10,7 @@ namespace Binance.API.Csharp.Client.Utils /// public static class Utilities { + public static long DeltaTimeAdjustment { get; set; } = 0; /// /// Gets a HMACSHA256 signature based on the API Secret. /// @@ -36,7 +37,7 @@ public static string GenerateSignature(string apiSecret, string message) public static string GenerateTimeStamp(DateTime baseDateTime) { var dtOffset = new DateTimeOffset(baseDateTime); - return dtOffset.ToUnixTimeMilliseconds().ToString(); + return (dtOffset.ToUnixTimeMilliseconds() + DeltaTimeAdjustment).ToString(); } /// From 3d48b345b76af1b6f3a9aab99e8b573e85faeff8 Mon Sep 17 00:00:00 2001 From: MaVaL Date: Fri, 26 Jan 2018 18:51:20 +0300 Subject: [PATCH 06/21] Fix code for corret solution build --- Binance.API.Csharp.Client/ApiClient.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Binance.API.Csharp.Client/ApiClient.cs b/Binance.API.Csharp.Client/ApiClient.cs index 19a0712..42ba153 100644 --- a/Binance.API.Csharp.Client/ApiClient.cs +++ b/Binance.API.Csharp.Client/ApiClient.cs @@ -110,7 +110,7 @@ public void ConnectToWebSocket(string parameters, MessageHandler messageHa { var customParser = new CustomParser(); var datum = JsonConvert.DeserializeObject(e.Data); - if (datum is JObject jobj) + if (datum is JObject) { if (datum["lastUpdateId"] != null) eventData = customParser.GetParsedDepthPartialMessage(datum); @@ -157,7 +157,7 @@ public void ConnectToUserDataWebSocket(string parameters, MessageHandler(e.Data); - switch (eventData.e.Value) + switch ((string)eventData.e.Value) { case "outboundAccountInfo": accountHandler(JsonConvert.DeserializeObject(e.Data)); From c8cf26f9fa4ac74e0b3caee492c0452864545b92 Mon Sep 17 00:00:00 2001 From: MaVaL Date: Fri, 26 Jan 2018 19:41:49 +0300 Subject: [PATCH 07/21] ExchangeInfo APi Unit test enter for debug --- Binance.API.Csharp.Client.Test/BinanceTest.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Binance.API.Csharp.Client.Test/BinanceTest.cs b/Binance.API.Csharp.Client.Test/BinanceTest.cs index 03d6216..350fbac 100644 --- a/Binance.API.Csharp.Client.Test/BinanceTest.cs +++ b/Binance.API.Csharp.Client.Test/BinanceTest.cs @@ -23,6 +23,13 @@ public void GetServerTime() { var serverTime = binanceClient.GetServerTime().Result; } + + [TestMethod] + public void ExchangeInfo() + { + var rules = binanceClient.GetTradingRulesAsync().Result; + Thread.Sleep(1000); + } #endregion #region Market Data From 77c246a0ba319f4f13874543f87164a71aa76cd0 Mon Sep 17 00:00:00 2001 From: MaVaL Date: Fri, 26 Jan 2018 18:51:20 +0300 Subject: [PATCH 08/21] Fix code for corret solution build --- Binance.API.Csharp.Client/ApiClient.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Binance.API.Csharp.Client/ApiClient.cs b/Binance.API.Csharp.Client/ApiClient.cs index 19a0712..42ba153 100644 --- a/Binance.API.Csharp.Client/ApiClient.cs +++ b/Binance.API.Csharp.Client/ApiClient.cs @@ -110,7 +110,7 @@ public void ConnectToWebSocket(string parameters, MessageHandler messageHa { var customParser = new CustomParser(); var datum = JsonConvert.DeserializeObject(e.Data); - if (datum is JObject jobj) + if (datum is JObject) { if (datum["lastUpdateId"] != null) eventData = customParser.GetParsedDepthPartialMessage(datum); @@ -157,7 +157,7 @@ public void ConnectToUserDataWebSocket(string parameters, MessageHandler(e.Data); - switch (eventData.e.Value) + switch ((string)eventData.e.Value) { case "outboundAccountInfo": accountHandler(JsonConvert.DeserializeObject(e.Data)); From 9b0bc17802b7875b115c78321b6c90bc9c738303 Mon Sep 17 00:00:00 2001 From: MaVaL Date: Fri, 26 Jan 2018 19:41:49 +0300 Subject: [PATCH 09/21] ExchangeInfo APi Unit test enter for debug --- Binance.API.Csharp.Client.Test/BinanceTest.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Binance.API.Csharp.Client.Test/BinanceTest.cs b/Binance.API.Csharp.Client.Test/BinanceTest.cs index 03d6216..350fbac 100644 --- a/Binance.API.Csharp.Client.Test/BinanceTest.cs +++ b/Binance.API.Csharp.Client.Test/BinanceTest.cs @@ -23,6 +23,13 @@ public void GetServerTime() { var serverTime = binanceClient.GetServerTime().Result; } + + [TestMethod] + public void ExchangeInfo() + { + var rules = binanceClient.GetTradingRulesAsync().Result; + Thread.Sleep(1000); + } #endregion #region Market Data From 0a6bf0608fed061818ff083bec94780f4264e38b Mon Sep 17 00:00:00 2001 From: MaVaL Date: Sat, 27 Jan 2018 23:46:46 +0300 Subject: [PATCH 10/21] InvariantCulture for decimal parse --- .../Utils/CustomParser.cs | 53 ++++++++++++++----- 1 file changed, 39 insertions(+), 14 deletions(-) diff --git a/Binance.API.Csharp.Client/Utils/CustomParser.cs b/Binance.API.Csharp.Client/Utils/CustomParser.cs index 561a8df..f32e577 100644 --- a/Binance.API.Csharp.Client/Utils/CustomParser.cs +++ b/Binance.API.Csharp.Client/Utils/CustomParser.cs @@ -2,6 +2,7 @@ using Binance.API.Csharp.Client.Models.WebSocket; using Newtonsoft.Json.Linq; using System.Collections.Generic; +using System.Globalization; using System.Linq; namespace Binance.API.Csharp.Client.Utils @@ -28,12 +29,20 @@ public OrderBook GetParsedOrderBook(dynamic orderBookData) foreach (JToken item in ((JArray)orderBookData.bids).ToArray()) { - bids.Add(new OrderBookOffer() { Price = decimal.Parse(item[0].ToString()), Quantity = decimal.Parse(item[1].ToString()) }); + bids.Add(new OrderBookOffer + { + Price = decimal.Parse(item[0].ToString(), CultureInfo.InvariantCulture), + Quantity = decimal.Parse(item[1].ToString(), CultureInfo.InvariantCulture) + }); } foreach (JToken item in ((JArray)orderBookData.asks).ToArray()) { - asks.Add(new OrderBookOffer() { Price = decimal.Parse(item[0].ToString()), Quantity = decimal.Parse(item[1].ToString()) }); + asks.Add(new OrderBookOffer + { + Price = decimal.Parse(item[0].ToString(), CultureInfo.InvariantCulture), + Quantity = decimal.Parse(item[1].ToString(), CultureInfo.InvariantCulture) + }); } result.Bids = bids; @@ -56,16 +65,16 @@ public IEnumerable GetParsedCandlestick(dynamic candlestickData) result.Add(new Candlestick() { OpenTime = long.Parse(item[0].ToString()), - Open = decimal.Parse(item[1].ToString()), - High = decimal.Parse(item[2].ToString()), - Low = decimal.Parse(item[3].ToString()), - Close = decimal.Parse(item[4].ToString()), - Volume = decimal.Parse(item[5].ToString()), + Open = decimal.Parse(item[1].ToString(), CultureInfo.InvariantCulture), + High = decimal.Parse(item[2].ToString(), CultureInfo.InvariantCulture), + Low = decimal.Parse(item[3].ToString(), CultureInfo.InvariantCulture), + Close = decimal.Parse(item[4].ToString(), CultureInfo.InvariantCulture), + Volume = decimal.Parse(item[5].ToString(), CultureInfo.InvariantCulture), CloseTime = long.Parse(item[6].ToString()), - QuoteAssetVolume = decimal.Parse(item[7].ToString()), + QuoteAssetVolume = decimal.Parse(item[7].ToString(), CultureInfo.InvariantCulture), NumberOfTrades = int.Parse(item[8].ToString()), - TakerBuyBaseAssetVolume = decimal.Parse(item[9].ToString()), - TakerBuyQuoteAssetVolume = decimal.Parse(item[10].ToString()) + TakerBuyBaseAssetVolume = decimal.Parse(item[9].ToString(), CultureInfo.InvariantCulture), + TakerBuyQuoteAssetVolume = decimal.Parse(item[10].ToString(), CultureInfo.InvariantCulture) }); } @@ -87,12 +96,20 @@ public DepthMessage GetParsedDepthMessage(dynamic messageData) foreach (JToken item in ((JArray)messageData.b).ToArray()) { - bids.Add(new OrderBookOffer() { Price = decimal.Parse(item[0].ToString()), Quantity = decimal.Parse(item[1].ToString()) }); + bids.Add(new OrderBookOffer + { + Price = decimal.Parse(item[0].ToString(), CultureInfo.InvariantCulture), + Quantity = decimal.Parse(item[1].ToString(), CultureInfo.InvariantCulture) + }); } foreach (JToken item in ((JArray)messageData.a).ToArray()) { - asks.Add(new OrderBookOffer() { Price = decimal.Parse(item[0].ToString()), Quantity = decimal.Parse(item[1].ToString()) }); + asks.Add(new OrderBookOffer + { + Price = decimal.Parse(item[0].ToString(), CultureInfo.InvariantCulture), + Quantity = decimal.Parse(item[1].ToString(), CultureInfo.InvariantCulture) + }); } result.Bids = bids; @@ -113,12 +130,20 @@ public DepthPartialMessage GetParsedDepthPartialMessage(dynamic messageData) foreach (JToken item in ((JArray)messageData.bids).ToArray()) { - bids.Add(new OrderBookOffer() { Price = decimal.Parse(item[0].ToString()), Quantity = decimal.Parse(item[1].ToString()) }); + bids.Add(new OrderBookOffer() + { + Price = decimal.Parse(item[0].ToString(), CultureInfo.InvariantCulture), + Quantity = decimal.Parse(item[1].ToString(), CultureInfo.InvariantCulture) + }); } foreach (JToken item in ((JArray)messageData.asks).ToArray()) { - asks.Add(new OrderBookOffer() { Price = decimal.Parse(item[0].ToString()), Quantity = decimal.Parse(item[1].ToString()) }); + asks.Add(new OrderBookOffer() + { + Price = decimal.Parse(item[0].ToString(), CultureInfo.InvariantCulture), + Quantity = decimal.Parse(item[1].ToString(), CultureInfo.InvariantCulture) + }); } result.Bids = bids; From 66c87696c6f3b7ca2289f31ce511f93f28c81f46 Mon Sep 17 00:00:00 2001 From: MaVaL Date: Sun, 28 Jan 2018 16:14:53 +0300 Subject: [PATCH 11/21] Change work whis WebSocket events --- Binance.API.Csharp.Client/ApiClient.cs | 40 ++++++++++++++------------ 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/Binance.API.Csharp.Client/ApiClient.cs b/Binance.API.Csharp.Client/ApiClient.cs index 42ba153..fc1050b 100644 --- a/Binance.API.Csharp.Client/ApiClient.cs +++ b/Binance.API.Csharp.Client/ApiClient.cs @@ -25,6 +25,7 @@ public class ApiClient : ApiClientAbstract, IApiClient public ApiClient(string apiKey, string apiSecret, string apiUrl = @"https://www.binance.com", string webSocketEndpoint = @"wss://stream.binance.com:9443/ws/", bool addDefaultHeaders = true) : base(apiKey, apiSecret, apiUrl, webSocketEndpoint, addDefaultHeaders) { } + /// /// Calls API Methods. @@ -43,7 +44,7 @@ public async Task CallAsync(ApiMethod method, string endpoint, bool isSign { // Joining provided parameters parameters += (!string.IsNullOrWhiteSpace(parameters) ? "×tamp=" : "timestamp=") +( Utilities.GenerateTimeStamp(DateTime.Now.ToUniversalTime()) ); - + // Creating request signature var signature = Utilities.GenerateSignature(_apiSecret, parameters); finalEndpoint = $"{endpoint}?{parameters}&signature={signature}"; @@ -133,21 +134,22 @@ public void ConnectToWebSocket(string parameters, MessageHandler messageHa ws.OnError += (sender, e) => { - _openSockets.Remove(ws); - }; - ws.Connect(); - _openSockets.Add(ws); - } - - /// - /// Connects to a UserData Websocket endpoint. - /// - /// Paremeters to send to the Websocket. - /// Deletage to callback after receive a account info message. - /// Deletage to callback after receive a trade message. - /// Deletage to callback after receive a order message. - public void ConnectToUserDataWebSocket(string parameters, MessageHandler accountHandler, MessageHandler tradeHandler, MessageHandler orderHandler) + if (ws.ReadyState != WebSocketState.Open) + _openSockets.Remove(ws); + }; + ws.OnOpen += (s, e) => _openSockets.Add(ws); + ws.Connect(); + } + + /// + /// Connects to a UserData Websocket endpoint. + /// + /// Paremeters to send to the Websocket. + /// Deletage to callback after receive a account info message. + /// Deletage to callback after receive a trade message. + /// Deletage to callback after receive a order message. + public void ConnectToUserDataWebSocket(string parameters, MessageHandler accountHandler, MessageHandler tradeHandler, MessageHandler orderHandler) { var finalEndpoint = _webSocketEndpoint + parameters; @@ -184,11 +186,11 @@ public void ConnectToUserDataWebSocket(string parameters, MessageHandler { - _openSockets.Remove(ws); + if (ws.ReadyState != WebSocketState.Open) + _openSockets.Remove(ws); }; - - ws.Connect(); - _openSockets.Add(ws); + ws.OnOpen += (s, e) => _openSockets.Add(ws); + ws.Connect(); } } } From 707f2d06f2ebc943f551a9bc351f8ce930a1cdd6 Mon Sep 17 00:00:00 2001 From: MaVaL Date: Sun, 28 Jan 2018 16:47:47 +0300 Subject: [PATCH 12/21] Return WebSocket object for external use --- .../Interfaces/IApiClient.cs | 33 ++++++----- .../Interfaces/IBinanceClient.cs | 45 +++++++------- Binance.API.Csharp.Client/ApiClient.cs | 58 ++++++++++--------- Binance.API.Csharp.Client/BinanceClient.cs | 50 ++++++++-------- 4 files changed, 98 insertions(+), 88 deletions(-) diff --git a/Binance.API.Csharp.Client.Domain/Interfaces/IApiClient.cs b/Binance.API.Csharp.Client.Domain/Interfaces/IApiClient.cs index 65dc01f..8383ff4 100644 --- a/Binance.API.Csharp.Client.Domain/Interfaces/IApiClient.cs +++ b/Binance.API.Csharp.Client.Domain/Interfaces/IApiClient.cs @@ -1,6 +1,7 @@ using Binance.API.Csharp.Client.Models.Enums; using Binance.API.Csharp.Client.Models.WebSocket; using System.Threading.Tasks; +using WebSocketSharp; using static Binance.API.Csharp.Client.Domain.Abstract.ApiClientAbstract; namespace Binance.API.Csharp.Client.Domain.Interfaces @@ -18,22 +19,22 @@ public interface IApiClient /// Task CallAsync(ApiMethod method, string endpoint, bool isSigned = false, string parameters = null); - /// - /// Connects to a Websocket endpoint. - /// - /// Type used to parsed the response message. - /// Paremeters to send to the Websocket. - /// Deletage to callback after receive a message. - /// Specifies if needs to use a custom parser for the response message. - void ConnectToWebSocket(string parameters, MessageHandler messageDelegate, bool useCustomParser = false); + /// + /// Connects to a Websocket endpoint. + /// + /// Type used to parsed the response message. + /// Paremeters to send to the Websocket. + /// Deletage to callback after receive a message. + /// Specifies if needs to use a custom parser for the response message. + WebSocket ConnectToWebSocket(string parameters, MessageHandler messageDelegate, bool useCustomParser = false); - /// - /// Connects to a UserData Websocket endpoint. - /// - /// Paremeters to send to the Websocket. - /// Deletage to callback after receive a account info message. - /// Deletage to callback after receive a trade message. - /// Deletage to callback after receive a order message. - void ConnectToUserDataWebSocket(string parameters, MessageHandler accountHandler, MessageHandler tradeHandler, MessageHandler orderHandler); + /// + /// Connects to a UserData Websocket endpoint. + /// + /// Paremeters to send to the Websocket. + /// Deletage to callback after receive a account info message. + /// Deletage to callback after receive a trade message. + /// Deletage to callback after receive a order message. + WebSocket ConnectToUserDataWebSocket(string parameters, MessageHandler accountHandler, MessageHandler tradeHandler, MessageHandler orderHandler); } } \ No newline at end of file diff --git a/Binance.API.Csharp.Client.Domain/Interfaces/IBinanceClient.cs b/Binance.API.Csharp.Client.Domain/Interfaces/IBinanceClient.cs index 5312215..53b9b53 100644 --- a/Binance.API.Csharp.Client.Domain/Interfaces/IBinanceClient.cs +++ b/Binance.API.Csharp.Client.Domain/Interfaces/IBinanceClient.cs @@ -7,6 +7,7 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; +using WebSocketSharp; using static Binance.API.Csharp.Client.Domain.Abstract.ApiClientAbstract; namespace Binance.API.Csharp.Client.Domain.Interfaces @@ -210,27 +211,31 @@ public interface IBinanceClient #endregion #region WebSocket - /// - /// Listen to the Depth endpoint. - /// - /// Ticker symbol. - /// Handler to be used when a message is received. - void ListenDepthEndpoint(string symbol, MessageHandler messageHandler); - /// - /// Listen to the Kline endpoint. - /// - /// Ticker symbol. - /// Time interval to retreive. - /// Handler to be used when a message is received. - void ListenKlineEndpoint(string symbol, TimeInterval interval, MessageHandler messageHandler); - - /// - /// Listen to the Trades endpoint. - /// - /// Ticker symbol. - /// Handler to be used when a message is received. - void ListenTradeEndpoint(string symbol, MessageHandler messageHandler); + /// + /// Listen to the Depth endpoint. + /// + /// Ticker symbol. + /// + /// Handler to be used when a message is received. + WebSocket ListenDepthEndpoint(string symbol, MessageHandler messageHandler); + + /// + /// Listen to the Kline endpoint. + /// + /// Ticker symbol. + /// Time interval to retreive. + /// + /// Handler to be used when a message is received. + WebSocket ListenKlineEndpoint(string symbol, TimeInterval interval, MessageHandler messageHandler); + + /// + /// Listen to the Trades endpoint. + /// + /// Ticker symbol. + /// + /// Handler to be used when a message is received. + WebSocket ListenTradeEndpoint(string symbol, MessageHandler messageHandler); /// /// Listen to the User Data endpoint. diff --git a/Binance.API.Csharp.Client/ApiClient.cs b/Binance.API.Csharp.Client/ApiClient.cs index fc1050b..4947e7b 100644 --- a/Binance.API.Csharp.Client/ApiClient.cs +++ b/Binance.API.Csharp.Client/ApiClient.cs @@ -27,16 +27,16 @@ public ApiClient(string apiKey, string apiSecret, string apiUrl = @"https://www. } - /// - /// Calls API Methods. - /// - /// Type to which the response content will be converted. - /// HTTPMethod (POST-GET-PUT-DELETE) - /// Url endpoing. - /// Specifies if the request needs a signature. - /// Request parameters. - /// - public async Task CallAsync(ApiMethod method, string endpoint, bool isSigned = false, string parameters = null) + /// + /// Calls API Methods. + /// + /// Type to which the response content will be converted. + /// HTTPMethod (POST-GET-PUT-DELETE) + /// Url endpoing. + /// Specifies if the request needs a signature. + /// Request parameters. + /// + public async Task CallAsync(ApiMethod method, string endpoint, bool isSigned = false, string parameters = null) { var finalEndpoint = endpoint + (string.IsNullOrWhiteSpace(parameters) ? "" : $"?{parameters}"); @@ -90,14 +90,14 @@ public async Task CallAsync(ApiMethod method, string endpoint, bool isSign throw new Exception(string.Format("Api Error Code: {0} Message: {1}", eCode, eMsg)); } - /// - /// Connects to a Websocket endpoint. - /// - /// Type used to parsed the response message. - /// Paremeters to send to the Websocket. - /// Deletage to callback after receive a message. - /// Specifies if needs to use a custom parser for the response message. - public void ConnectToWebSocket(string parameters, MessageHandler messageHandler, bool useCustomParser = false) + /// + /// Connects to a Websocket endpoint. + /// + /// Type used to parsed the response message. + /// Paremeters to send to the Websocket. + /// Deletage to callback after receive a message. + /// Specifies if needs to use a custom parser for the response message. + public WebSocket ConnectToWebSocket(string parameters, MessageHandler messageHandler, bool useCustomParser = false) { var finalEndpoint = _webSocketEndpoint + parameters; @@ -140,16 +140,17 @@ public void ConnectToWebSocket(string parameters, MessageHandler messageHa }; ws.OnOpen += (s, e) => _openSockets.Add(ws); ws.Connect(); - } - - /// - /// Connects to a UserData Websocket endpoint. - /// - /// Paremeters to send to the Websocket. - /// Deletage to callback after receive a account info message. - /// Deletage to callback after receive a trade message. - /// Deletage to callback after receive a order message. - public void ConnectToUserDataWebSocket(string parameters, MessageHandler accountHandler, MessageHandler tradeHandler, MessageHandler orderHandler) + return ws; + } + + /// + /// Connects to a UserData Websocket endpoint. + /// + /// Paremeters to send to the Websocket. + /// Deletage to callback after receive a account info message. + /// Deletage to callback after receive a trade message. + /// Deletage to callback after receive a order message. + public WebSocket ConnectToUserDataWebSocket(string parameters, MessageHandler accountHandler, MessageHandler tradeHandler, MessageHandler orderHandler) { var finalEndpoint = _webSocketEndpoint + parameters; @@ -191,6 +192,7 @@ public void ConnectToUserDataWebSocket(string parameters, MessageHandler _openSockets.Add(ws); ws.Connect(); + return ws; } } } diff --git a/Binance.API.Csharp.Client/BinanceClient.cs b/Binance.API.Csharp.Client/BinanceClient.cs index 78fb132..65e3b2a 100644 --- a/Binance.API.Csharp.Client/BinanceClient.cs +++ b/Binance.API.Csharp.Client/BinanceClient.cs @@ -12,6 +12,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using WebSocketSharp; namespace Binance.API.Csharp.Client { @@ -569,12 +570,13 @@ public async Task CloseUserStream(string listenKey) #endregion #region Web Socket Client - /// - /// Listen to the Depth endpoint. - /// - /// Ticker symbol. - /// Handler to be used when a message is received. - public void ListenDepthEndpoint(string symbol, ApiClientAbstract.MessageHandler depthHandler) + + /// + /// Listen to the Depth endpoint. + /// + /// Ticker symbol. + /// Handler to be used when a message is received. + public WebSocket ListenDepthEndpoint(string symbol, ApiClientAbstract.MessageHandler depthHandler) { if (string.IsNullOrWhiteSpace(symbol)) { @@ -582,10 +584,10 @@ public void ListenDepthEndpoint(string symbol, ApiClientAbstract.MessageHandler< } var param = symbol + "@depth"; - _apiClient.ConnectToWebSocket(param, depthHandler, true); + return _apiClient.ConnectToWebSocket(param, depthHandler, true); } - public void ListenPartialDepthEndPoint(string symbol,int levels, ApiClientAbstract.MessageHandler depthHandler) + public WebSocket ListenPartialDepthEndPoint(string symbol,int levels, ApiClientAbstract.MessageHandler depthHandler) { if (string.IsNullOrWhiteSpace(symbol)) { @@ -594,16 +596,16 @@ public void ListenPartialDepthEndPoint(string symbol,int levels, ApiClientAbstra if (levels != 5 && levels != 10 && levels != 20) throw new ArgumentException("Valid values for level are 5,10 or 20"); var param = symbol.ToLower() + "@depth" + levels; - _apiClient.ConnectToWebSocket(param, depthHandler, true); + return _apiClient.ConnectToWebSocket(param, depthHandler, true); } - /// - /// Listen to the Kline endpoint. - /// - /// Ticker symbol. - /// Time interval to retreive. - /// Handler to be used when a message is received. - public void ListenKlineEndpoint(string symbol, TimeInterval interval, ApiClientAbstract.MessageHandler klineHandler) + /// + /// Listen to the Kline endpoint. + /// + /// Ticker symbol. + /// Time interval to retreive. + /// Handler to be used when a message is received. + public WebSocket ListenKlineEndpoint(string symbol, TimeInterval interval, ApiClientAbstract.MessageHandler klineHandler) { if (string.IsNullOrWhiteSpace(symbol)) { @@ -611,15 +613,15 @@ public void ListenKlineEndpoint(string symbol, TimeInterval interval, ApiClientA } var param = symbol + $"@kline_{interval.GetDescription()}"; - _apiClient.ConnectToWebSocket(param, klineHandler); + return _apiClient.ConnectToWebSocket(param, klineHandler); } - /// - /// Listen to the Trades endpoint. - /// - /// Ticker symbol. - /// Handler to be used when a message is received. - public void ListenTradeEndpoint(string symbol, ApiClientAbstract.MessageHandler tradeHandler) + /// + /// Listen to the Trades endpoint. + /// + /// Ticker symbol. + /// Handler to be used when a message is received. + public WebSocket ListenTradeEndpoint(string symbol, ApiClientAbstract.MessageHandler tradeHandler) { if (string.IsNullOrWhiteSpace(symbol)) { @@ -627,7 +629,7 @@ public void ListenTradeEndpoint(string symbol, ApiClientAbstract.MessageHandler< } var param = symbol + "@aggTrade"; - _apiClient.ConnectToWebSocket(param, tradeHandler); + return _apiClient.ConnectToWebSocket(param, tradeHandler); } /// From 2b66674133c90aaa2d6b80cc9ec62eaeb6fcf67c Mon Sep 17 00:00:00 2001 From: "F.Buldo" Date: Sun, 28 Jan 2018 19:00:44 +0100 Subject: [PATCH 13/21] quantity parameter of PostNewOrderTest method should have maximum 20 decimal digits --- Binance.API.Csharp.Client/BinanceClient.cs | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/Binance.API.Csharp.Client/BinanceClient.cs b/Binance.API.Csharp.Client/BinanceClient.cs index 78fb132..06d0ab3 100644 --- a/Binance.API.Csharp.Client/BinanceClient.cs +++ b/Binance.API.Csharp.Client/BinanceClient.cs @@ -58,6 +58,12 @@ private void ValidateOrderValue(string symbol, OrderType orderType, decimal unit } } + //quantity needs to be conform to this regex "^([0-9]{1,20})(\.[0-9]{1,20})?$" -> 20 decimal digits + if (quantity != decimal.Round(quantity, 20)) + { + throw new ArgumentException("Quantity parameter should have no mora than 20 decimal digits."); + } + // Validating Trading Rules if (_tradingRules != null) { @@ -258,8 +264,10 @@ public async Task PostNewOrder(string symbol, decimal quantity, decima { //Validates that the order is valid. ValidateOrderValue(symbol, orderType, price, quantity, icebergQty); - - var args = $"symbol={symbol.ToUpper()}&side={side}&type={orderType}&quantity={quantity}" + //quantity needs to be conform to this regex ^([0-9]{1,20})(\.[0-9]{1,20})?$ -> 20 decimal digits + quantity = decimal.Round(quantity, 20); + var args = $"symbol={symbol.ToUpper()}&side={side}&type={orderType}" + + $"&quantity={quantity}" + (orderType == OrderType.LIMIT ? $"&timeInForce={timeInForce}" : "") + (orderType == OrderType.LIMIT ? $"&price={price}" : "") + (icebergQty > 0m ? $"&icebergQty={icebergQty}" : "") @@ -284,8 +292,10 @@ public async Task PostNewOrderTest(string symbol, decimal quantity, dec { //Validates that the order is valid. ValidateOrderValue(symbol, orderType, price, quantity, icebergQty); - - var args = $"symbol={symbol.ToUpper()}&side={side}&type={orderType}&quantity={quantity}" + //quantity needs to be conform to this regex ^([0-9]{1,20})(\.[0-9]{1,20})?$ -> 20 decimal digits + quantity = decimal.Round(quantity, 20); + var args = $"symbol={symbol.ToUpper()}&side={side}&type={orderType}" + + $"&quantity={quantity}" //quantity needs to be conform to this regex ^([0-9]{1,20})(\.[0-9]{1,20})?$ + (orderType == OrderType.LIMIT ? $"&timeInForce={timeInForce}" : "") + (orderType == OrderType.LIMIT ? $"&price={price}" : "") + (icebergQty > 0m ? $"&icebergQty={icebergQty}" : "") @@ -585,7 +595,7 @@ public void ListenDepthEndpoint(string symbol, ApiClientAbstract.MessageHandler< _apiClient.ConnectToWebSocket(param, depthHandler, true); } - public void ListenPartialDepthEndPoint(string symbol,int levels, ApiClientAbstract.MessageHandler depthHandler) + public void ListenPartialDepthEndPoint(string symbol, int levels, ApiClientAbstract.MessageHandler depthHandler) { if (string.IsNullOrWhiteSpace(symbol)) { From e1e1268cb9227f664debcd72d5b5eadc87b4dbb6 Mon Sep 17 00:00:00 2001 From: "F.Buldo" Date: Sun, 28 Jan 2018 19:12:01 +0100 Subject: [PATCH 14/21] fix build error --- .../Binance.API.Csharp.Client.Test.csproj | 3 +++ Binance.API.Csharp.Client.Test/packages.config | 1 + 2 files changed, 4 insertions(+) diff --git a/Binance.API.Csharp.Client.Test/Binance.API.Csharp.Client.Test.csproj b/Binance.API.Csharp.Client.Test/Binance.API.Csharp.Client.Test.csproj index 4757297..0b646ed 100644 --- a/Binance.API.Csharp.Client.Test/Binance.API.Csharp.Client.Test.csproj +++ b/Binance.API.Csharp.Client.Test/Binance.API.Csharp.Client.Test.csproj @@ -51,6 +51,9 @@ + + ..\packages\WebSocketSharp-NonPreRelease.1.0.0\lib\net35\websocket-sharp.dll + diff --git a/Binance.API.Csharp.Client.Test/packages.config b/Binance.API.Csharp.Client.Test/packages.config index 213bc4b..7a4429d 100644 --- a/Binance.API.Csharp.Client.Test/packages.config +++ b/Binance.API.Csharp.Client.Test/packages.config @@ -3,4 +3,5 @@ + \ No newline at end of file From 8d304919ef819a139bee132dc4fab5a7775b46e9 Mon Sep 17 00:00:00 2001 From: "F.Buldo" Date: Sun, 28 Jan 2018 19:12:19 +0100 Subject: [PATCH 15/21] untabify --- Binance.API.Csharp.Client/BinanceClient.cs | 38 +++++++++++----------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/Binance.API.Csharp.Client/BinanceClient.cs b/Binance.API.Csharp.Client/BinanceClient.cs index eb8ab40..e5e42f6 100644 --- a/Binance.API.Csharp.Client/BinanceClient.cs +++ b/Binance.API.Csharp.Client/BinanceClient.cs @@ -581,12 +581,12 @@ public async Task CloseUserStream(string listenKey) #region Web Socket Client - /// - /// Listen to the Depth endpoint. - /// - /// Ticker symbol. - /// Handler to be used when a message is received. - public WebSocket ListenDepthEndpoint(string symbol, ApiClientAbstract.MessageHandler depthHandler) + /// + /// Listen to the Depth endpoint. + /// + /// Ticker symbol. + /// Handler to be used when a message is received. + public WebSocket ListenDepthEndpoint(string symbol, ApiClientAbstract.MessageHandler depthHandler) { if (string.IsNullOrWhiteSpace(symbol)) { @@ -609,13 +609,13 @@ public WebSocket ListenPartialDepthEndPoint(string symbol,int levels, ApiClientA return _apiClient.ConnectToWebSocket(param, depthHandler, true); } - /// - /// Listen to the Kline endpoint. - /// - /// Ticker symbol. - /// Time interval to retreive. - /// Handler to be used when a message is received. - public WebSocket ListenKlineEndpoint(string symbol, TimeInterval interval, ApiClientAbstract.MessageHandler klineHandler) + /// + /// Listen to the Kline endpoint. + /// + /// Ticker symbol. + /// Time interval to retreive. + /// Handler to be used when a message is received. + public WebSocket ListenKlineEndpoint(string symbol, TimeInterval interval, ApiClientAbstract.MessageHandler klineHandler) { if (string.IsNullOrWhiteSpace(symbol)) { @@ -626,12 +626,12 @@ public WebSocket ListenKlineEndpoint(string symbol, TimeInterval interval, ApiCl return _apiClient.ConnectToWebSocket(param, klineHandler); } - /// - /// Listen to the Trades endpoint. - /// - /// Ticker symbol. - /// Handler to be used when a message is received. - public WebSocket ListenTradeEndpoint(string symbol, ApiClientAbstract.MessageHandler tradeHandler) + /// + /// Listen to the Trades endpoint. + /// + /// Ticker symbol. + /// Handler to be used when a message is received. + public WebSocket ListenTradeEndpoint(string symbol, ApiClientAbstract.MessageHandler tradeHandler) { if (string.IsNullOrWhiteSpace(symbol)) { From 5894decc5688efeef8c66a25f9bf2ff609c055f9 Mon Sep 17 00:00:00 2001 From: "F.Buldo" Date: Mon, 29 Jan 2018 23:21:06 +0100 Subject: [PATCH 16/21] Added callback for detecting socket disconnection --- .../Interfaces/IApiClient.cs | 13 ++- .../Interfaces/IBinanceClient.cs | 8 +- Binance.API.Csharp.Client/ApiClient.cs | 97 ++++++++++--------- Binance.API.Csharp.Client/BinanceClient.cs | 22 ++--- 4 files changed, 75 insertions(+), 65 deletions(-) diff --git a/Binance.API.Csharp.Client.Domain/Interfaces/IApiClient.cs b/Binance.API.Csharp.Client.Domain/Interfaces/IApiClient.cs index 8383ff4..b9461db 100644 --- a/Binance.API.Csharp.Client.Domain/Interfaces/IApiClient.cs +++ b/Binance.API.Csharp.Client.Domain/Interfaces/IApiClient.cs @@ -1,5 +1,6 @@ using Binance.API.Csharp.Client.Models.Enums; using Binance.API.Csharp.Client.Models.WebSocket; +using System; using System.Threading.Tasks; using WebSocketSharp; using static Binance.API.Csharp.Client.Domain.Abstract.ApiClientAbstract; @@ -26,7 +27,11 @@ public interface IApiClient /// Paremeters to send to the Websocket. /// Deletage to callback after receive a message. /// Specifies if needs to use a custom parser for the response message. - WebSocket ConnectToWebSocket(string parameters, MessageHandler messageDelegate, bool useCustomParser = false); + WebSocket ConnectToWebSocket( + string parameters, + MessageHandler messageDelegate, + Action onClose, + bool useCustomParser = false); /// /// Connects to a UserData Websocket endpoint. @@ -35,6 +40,10 @@ public interface IApiClient /// Deletage to callback after receive a account info message. /// Deletage to callback after receive a trade message. /// Deletage to callback after receive a order message. - WebSocket ConnectToUserDataWebSocket(string parameters, MessageHandler accountHandler, MessageHandler tradeHandler, MessageHandler orderHandler); + WebSocket ConnectToUserDataWebSocket(string parameters, + MessageHandler accountHandler, + MessageHandler tradeHandler, + MessageHandler orderHandler, + Action onClose); } } \ No newline at end of file diff --git a/Binance.API.Csharp.Client.Domain/Interfaces/IBinanceClient.cs b/Binance.API.Csharp.Client.Domain/Interfaces/IBinanceClient.cs index 53b9b53..fae8ae7 100644 --- a/Binance.API.Csharp.Client.Domain/Interfaces/IBinanceClient.cs +++ b/Binance.API.Csharp.Client.Domain/Interfaces/IBinanceClient.cs @@ -218,7 +218,7 @@ public interface IBinanceClient /// Ticker symbol. /// /// Handler to be used when a message is received. - WebSocket ListenDepthEndpoint(string symbol, MessageHandler messageHandler); + WebSocket ListenDepthEndpoint(string symbol, MessageHandler messageHandler, Action onClose); /// /// Listen to the Kline endpoint. @@ -227,7 +227,7 @@ public interface IBinanceClient /// Time interval to retreive. /// /// Handler to be used when a message is received. - WebSocket ListenKlineEndpoint(string symbol, TimeInterval interval, MessageHandler messageHandler); + WebSocket ListenKlineEndpoint(string symbol, TimeInterval interval, MessageHandler messageHandler, Action onClose); /// /// Listen to the Trades endpoint. @@ -235,7 +235,7 @@ public interface IBinanceClient /// Ticker symbol. /// /// Handler to be used when a message is received. - WebSocket ListenTradeEndpoint(string symbol, MessageHandler messageHandler); + WebSocket ListenTradeEndpoint(string symbol, MessageHandler messageHandler, Action onClose); /// /// Listen to the User Data endpoint. @@ -244,7 +244,7 @@ public interface IBinanceClient /// Handler to be used when a trade message is received. /// Handler to be used when a order message is received. /// - string ListenUserDataEndpoint(MessageHandler accountInfoHandler, MessageHandler tradesHandler, MessageHandler ordersHandler); + string ListenUserDataEndpoint(MessageHandler accountInfoHandler, MessageHandler tradesHandler, MessageHandler ordersHandler, Action onClose); #endregion } } diff --git a/Binance.API.Csharp.Client/ApiClient.cs b/Binance.API.Csharp.Client/ApiClient.cs index 4947e7b..831f2ef 100644 --- a/Binance.API.Csharp.Client/ApiClient.cs +++ b/Binance.API.Csharp.Client/ApiClient.cs @@ -25,26 +25,26 @@ public class ApiClient : ApiClientAbstract, IApiClient public ApiClient(string apiKey, string apiSecret, string apiUrl = @"https://www.binance.com", string webSocketEndpoint = @"wss://stream.binance.com:9443/ws/", bool addDefaultHeaders = true) : base(apiKey, apiSecret, apiUrl, webSocketEndpoint, addDefaultHeaders) { } - - - /// - /// Calls API Methods. - /// - /// Type to which the response content will be converted. - /// HTTPMethod (POST-GET-PUT-DELETE) - /// Url endpoing. - /// Specifies if the request needs a signature. - /// Request parameters. - /// - public async Task CallAsync(ApiMethod method, string endpoint, bool isSigned = false, string parameters = null) + + + /// + /// Calls API Methods. + /// + /// Type to which the response content will be converted. + /// HTTPMethod (POST-GET-PUT-DELETE) + /// Url endpoing. + /// Specifies if the request needs a signature. + /// Request parameters. + /// + public async Task CallAsync(ApiMethod method, string endpoint, bool isSigned = false, string parameters = null) { var finalEndpoint = endpoint + (string.IsNullOrWhiteSpace(parameters) ? "" : $"?{parameters}"); if (isSigned) { // Joining provided parameters - parameters += (!string.IsNullOrWhiteSpace(parameters) ? "×tamp=" : "timestamp=") +( Utilities.GenerateTimeStamp(DateTime.Now.ToUniversalTime()) ); - + parameters += (!string.IsNullOrWhiteSpace(parameters) ? "×tamp=" : "timestamp=") + (Utilities.GenerateTimeStamp(DateTime.Now.ToUniversalTime())); + // Creating request signature var signature = Utilities.GenerateSignature(_apiSecret, parameters); finalEndpoint = $"{endpoint}?{parameters}&signature={signature}"; @@ -86,18 +86,18 @@ public async Task CallAsync(ApiMethod method, string endpoint, bool isSign eMsg = i["msg"]?.Value(); } catch { } - } + } throw new Exception(string.Format("Api Error Code: {0} Message: {1}", eCode, eMsg)); } - /// - /// Connects to a Websocket endpoint. - /// - /// Type used to parsed the response message. - /// Paremeters to send to the Websocket. - /// Deletage to callback after receive a message. - /// Specifies if needs to use a custom parser for the response message. - public WebSocket ConnectToWebSocket(string parameters, MessageHandler messageHandler, bool useCustomParser = false) + /// + /// Connects to a Websocket endpoint. + /// + /// Type used to parsed the response message. + /// Paremeters to send to the Websocket. + /// Deletage to callback after receive a message. + /// Specifies if needs to use a custom parser for the response message. + public WebSocket ConnectToWebSocket(string parameters, MessageHandler messageHandler, Action onClose = null, bool useCustomParser = false) { var finalEndpoint = _webSocketEndpoint + parameters; @@ -111,13 +111,13 @@ public WebSocket ConnectToWebSocket(string parameters, MessageHandler mess { var customParser = new CustomParser(); var datum = JsonConvert.DeserializeObject(e.Data); - if (datum is JObject) + if (datum is JObject jobject) { - if (datum["lastUpdateId"] != null) - eventData = customParser.GetParsedDepthPartialMessage(datum); + if (jobject["lastUpdateId"] != null) + eventData = customParser.GetParsedDepthPartialMessage(jobject); else - eventData = customParser.GetParsedDepthMessage(datum); - } + eventData = customParser.GetParsedDepthMessage(jobject); + } } else { @@ -130,27 +130,27 @@ public WebSocket ConnectToWebSocket(string parameters, MessageHandler mess ws.OnClose += (sender, e) => { _openSockets.Remove(ws); + onClose?.Invoke(e); }; ws.OnError += (sender, e) => - { - - if (ws.ReadyState != WebSocketState.Open) - _openSockets.Remove(ws); + { + if (ws.ReadyState != WebSocketState.Open) + _openSockets.Remove(ws); }; - ws.OnOpen += (s, e) => _openSockets.Add(ws); - ws.Connect(); - return ws; + ws.OnOpen += (s, e) => _openSockets.Add(ws); + ws.Connect(); + return ws; } - /// - /// Connects to a UserData Websocket endpoint. - /// - /// Paremeters to send to the Websocket. - /// Deletage to callback after receive a account info message. - /// Deletage to callback after receive a trade message. - /// Deletage to callback after receive a order message. - public WebSocket ConnectToUserDataWebSocket(string parameters, MessageHandler accountHandler, MessageHandler tradeHandler, MessageHandler orderHandler) + /// + /// Connects to a UserData Websocket endpoint. + /// + /// Paremeters to send to the Websocket. + /// Deletage to callback after receive a account info message. + /// Deletage to callback after receive a trade message. + /// Deletage to callback after receive a order message. + public WebSocket ConnectToUserDataWebSocket(string parameters, MessageHandler accountHandler, MessageHandler tradeHandler, MessageHandler orderHandler, Action onClose = null) { var finalEndpoint = _webSocketEndpoint + parameters; @@ -183,16 +183,17 @@ public WebSocket ConnectToUserDataWebSocket(string parameters, MessageHandler { _openSockets.Remove(ws); + onClose?.Invoke(e); }; ws.OnError += (sender, e) => { - if (ws.ReadyState != WebSocketState.Open) - _openSockets.Remove(ws); + if (ws.ReadyState != WebSocketState.Open) + _openSockets.Remove(ws); }; - ws.OnOpen += (s, e) => _openSockets.Add(ws); - ws.Connect(); - return ws; + ws.OnOpen += (s, e) => _openSockets.Add(ws); + ws.Connect(); + return ws; } } } diff --git a/Binance.API.Csharp.Client/BinanceClient.cs b/Binance.API.Csharp.Client/BinanceClient.cs index e5e42f6..18ff5c7 100644 --- a/Binance.API.Csharp.Client/BinanceClient.cs +++ b/Binance.API.Csharp.Client/BinanceClient.cs @@ -17,7 +17,7 @@ namespace Binance.API.Csharp.Client { public class BinanceClient : BinanceClientAbstract, IBinanceClient - { + { /// /// ctor. /// @@ -586,7 +586,7 @@ public async Task CloseUserStream(string listenKey) /// /// Ticker symbol. /// Handler to be used when a message is received. - public WebSocket ListenDepthEndpoint(string symbol, ApiClientAbstract.MessageHandler depthHandler) + public WebSocket ListenDepthEndpoint(string symbol, ApiClientAbstract.MessageHandler depthHandler, Action onClose = null) { if (string.IsNullOrWhiteSpace(symbol)) { @@ -594,10 +594,10 @@ public WebSocket ListenDepthEndpoint(string symbol, ApiClientAbstract.MessageHan } var param = symbol + "@depth"; - return _apiClient.ConnectToWebSocket(param, depthHandler, true); + return _apiClient.ConnectToWebSocket(param, depthHandler, onClose, true); } - public WebSocket ListenPartialDepthEndPoint(string symbol,int levels, ApiClientAbstract.MessageHandler depthHandler) + public WebSocket ListenPartialDepthEndPoint(string symbol, int levels, ApiClientAbstract.MessageHandler depthHandler, Action onClose = null) { if (string.IsNullOrWhiteSpace(symbol)) { @@ -606,7 +606,7 @@ public WebSocket ListenPartialDepthEndPoint(string symbol,int levels, ApiClientA if (levels != 5 && levels != 10 && levels != 20) throw new ArgumentException("Valid values for level are 5,10 or 20"); var param = symbol.ToLower() + "@depth" + levels; - return _apiClient.ConnectToWebSocket(param, depthHandler, true); + return _apiClient.ConnectToWebSocket(param, depthHandler, onClose, true); } /// @@ -615,7 +615,7 @@ public WebSocket ListenPartialDepthEndPoint(string symbol,int levels, ApiClientA /// Ticker symbol. /// Time interval to retreive. /// Handler to be used when a message is received. - public WebSocket ListenKlineEndpoint(string symbol, TimeInterval interval, ApiClientAbstract.MessageHandler klineHandler) + public WebSocket ListenKlineEndpoint(string symbol, TimeInterval interval, ApiClientAbstract.MessageHandler klineHandler, Action onClose = null) { if (string.IsNullOrWhiteSpace(symbol)) { @@ -623,7 +623,7 @@ public WebSocket ListenKlineEndpoint(string symbol, TimeInterval interval, ApiCl } var param = symbol + $"@kline_{interval.GetDescription()}"; - return _apiClient.ConnectToWebSocket(param, klineHandler); + return _apiClient.ConnectToWebSocket(param, klineHandler, onClose); } /// @@ -631,7 +631,7 @@ public WebSocket ListenKlineEndpoint(string symbol, TimeInterval interval, ApiCl /// /// Ticker symbol. /// Handler to be used when a message is received. - public WebSocket ListenTradeEndpoint(string symbol, ApiClientAbstract.MessageHandler tradeHandler) + public WebSocket ListenTradeEndpoint(string symbol, ApiClientAbstract.MessageHandler tradeHandler, Action onClose = null) { if (string.IsNullOrWhiteSpace(symbol)) { @@ -639,7 +639,7 @@ public WebSocket ListenTradeEndpoint(string symbol, ApiClientAbstract.MessageHan } var param = symbol + "@aggTrade"; - return _apiClient.ConnectToWebSocket(param, tradeHandler); + return _apiClient.ConnectToWebSocket(param, tradeHandler, onClose); } /// @@ -649,11 +649,11 @@ public WebSocket ListenTradeEndpoint(string symbol, ApiClientAbstract.MessageHan /// Handler to be used when a trade message is received. /// Handler to be used when a order message is received. /// - public string ListenUserDataEndpoint(ApiClientAbstract.MessageHandler accountInfoHandler, ApiClientAbstract.MessageHandler tradesHandler, ApiClientAbstract.MessageHandler ordersHandler) + public string ListenUserDataEndpoint(ApiClientAbstract.MessageHandler accountInfoHandler, ApiClientAbstract.MessageHandler tradesHandler, ApiClientAbstract.MessageHandler ordersHandler, Action onClose = null) { var listenKey = StartUserStream().Result.ListenKey; - _apiClient.ConnectToUserDataWebSocket(listenKey, accountInfoHandler, tradesHandler, ordersHandler); + _apiClient.ConnectToUserDataWebSocket(listenKey, accountInfoHandler, tradesHandler, ordersHandler, onClose); return listenKey; } From 8877b5ca02e3e7036f5dd8c4aabbadca44f9dcf6 Mon Sep 17 00:00:00 2001 From: "F.Buldo" Date: Sat, 3 Feb 2018 16:04:27 +0100 Subject: [PATCH 17/21] FIX: Correct serializatio of OrderOrTradeUpdatedMessage --- .../WebSocket/OrderOrTradeUpdatedMessage.cs | 28 +++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/Binance.API.Csharp.Client.Models/WebSocket/OrderOrTradeUpdatedMessage.cs b/Binance.API.Csharp.Client.Models/WebSocket/OrderOrTradeUpdatedMessage.cs index dabe14d..0a3a450 100644 --- a/Binance.API.Csharp.Client.Models/WebSocket/OrderOrTradeUpdatedMessage.cs +++ b/Binance.API.Csharp.Client.Models/WebSocket/OrderOrTradeUpdatedMessage.cs @@ -11,7 +11,7 @@ public class OrderOrTradeUpdatedMessage [JsonProperty("s")] public string Symbol { get; set; } [JsonProperty("c")] - public string NewClientOrderId { get; set; } + public string NewClientOrderId { get; set; } [JsonProperty("S")] public string Side { get; set; } [JsonProperty("o")] @@ -22,6 +22,15 @@ public class OrderOrTradeUpdatedMessage public decimal OriginalQuantity { get; set; } [JsonProperty("p")] public decimal Price { get; set; } + [JsonProperty("P")] + public decimal StopPrice { get; set; } + [JsonProperty("F")] + public decimal IcebergQuantity { get; set; } + [JsonProperty("g")] + public int g { get; set; } + + [JsonProperty("C")] + public string OriginalClientOrderId { get; set; } [JsonProperty("x")] public string ExecutionType { get; set; } [JsonProperty("X")] @@ -29,7 +38,7 @@ public class OrderOrTradeUpdatedMessage [JsonProperty("r")] public string RejectReason { get; set; } [JsonProperty("i")] - public int Orderid { get; set; } + public int OrderId { get; set; } [JsonProperty("l")] public decimal LastFilledTradeQuantity { get; set; } [JsonProperty("z")] @@ -44,7 +53,22 @@ public class OrderOrTradeUpdatedMessage public long TradeTime { get; set; } [JsonProperty("t")] public int TradeId { get; set; } + [JsonProperty("I")] + public int I { get; set; } + [JsonProperty("w")] + public bool IsOrderWorking { get; set; } [JsonProperty("m")] public bool BuyerIsMaker { get; set; } + [JsonProperty("M")] + public bool M { get; set; } + [JsonProperty("O")] + public int O { get; set; } + [JsonProperty("Z")] + public decimal Z { get; set; } + + public override string ToString() + { + return JsonConvert.SerializeObject(this, Formatting.Indented); + } } } From 3f0d985f34517ea0981c23c92dd0fd3119688c99 Mon Sep 17 00:00:00 2001 From: "F.Buldo" Date: Sat, 3 Feb 2018 16:20:09 +0100 Subject: [PATCH 18/21] Addded clientOrderId feature --- .../Interfaces/IBinanceClient.cs | 54 +++++++++---------- Binance.API.Csharp.Client/BinanceClient.cs | 20 ++++--- 2 files changed, 38 insertions(+), 36 deletions(-) diff --git a/Binance.API.Csharp.Client.Domain/Interfaces/IBinanceClient.cs b/Binance.API.Csharp.Client.Domain/Interfaces/IBinanceClient.cs index fae8ae7..3a2c0d0 100644 --- a/Binance.API.Csharp.Client.Domain/Interfaces/IBinanceClient.cs +++ b/Binance.API.Csharp.Client.Domain/Interfaces/IBinanceClient.cs @@ -86,8 +86,7 @@ public interface IBinanceClient /// Indicates how long an order will remain active before it is executed or expires. /// Specific number of milliseconds the request is valid for. /// - Task PostNewOrder(string symbol, decimal quantity, decimal price, OrderSide side, OrderType orderType = OrderType.LIMIT, TimeInForce timeInForce = TimeInForce.GTC, decimal icebergQty = 0m, long recvWindow = 6000000); - + Task PostNewOrder(string symbol, decimal quantity, decimal price, OrderSide side, OrderType orderType = OrderType.LIMIT, TimeInForce timeInForce = TimeInForce.GTC, string clientOrderId = null, decimal icebergQty = 0m, long recvWindow = 5000); /// /// Test new order creation and signature/recvWindow long. Creates and validates a new order but does not send it into the matching engine. /// @@ -99,8 +98,7 @@ public interface IBinanceClient /// Indicates how long an order will remain active before it is executed or expires. /// Specific number of milliseconds the request is valid for. /// - Task PostNewOrderTest(string symbol, decimal quantity, decimal price, OrderSide side, OrderType orderType = OrderType.LIMIT, TimeInForce timeInForce = TimeInForce.GTC, decimal icebergQty = 0m, long recvWindow = 6000000); - + Task PostNewOrderTest(string symbol, decimal quantity, decimal price, OrderSide side, OrderType orderType = OrderType.LIMIT, TimeInForce timeInForce = TimeInForce.GTC, string clientOrderId = null, decimal icebergQty = 0m, long recvWindow = 5000); /// /// Check an order's status. /// @@ -212,30 +210,30 @@ public interface IBinanceClient #region WebSocket - /// - /// Listen to the Depth endpoint. - /// - /// Ticker symbol. - /// - /// Handler to be used when a message is received. - WebSocket ListenDepthEndpoint(string symbol, MessageHandler messageHandler, Action onClose); - - /// - /// Listen to the Kline endpoint. - /// - /// Ticker symbol. - /// Time interval to retreive. - /// - /// Handler to be used when a message is received. - WebSocket ListenKlineEndpoint(string symbol, TimeInterval interval, MessageHandler messageHandler, Action onClose); - - /// - /// Listen to the Trades endpoint. - /// - /// Ticker symbol. - /// - /// Handler to be used when a message is received. - WebSocket ListenTradeEndpoint(string symbol, MessageHandler messageHandler, Action onClose); + /// + /// Listen to the Depth endpoint. + /// + /// Ticker symbol. + /// + /// Handler to be used when a message is received. + WebSocket ListenDepthEndpoint(string symbol, MessageHandler messageHandler, Action onClose); + + /// + /// Listen to the Kline endpoint. + /// + /// Ticker symbol. + /// Time interval to retreive. + /// + /// Handler to be used when a message is received. + WebSocket ListenKlineEndpoint(string symbol, TimeInterval interval, MessageHandler messageHandler, Action onClose); + + /// + /// Listen to the Trades endpoint. + /// + /// Ticker symbol. + /// + /// Handler to be used when a message is received. + WebSocket ListenTradeEndpoint(string symbol, MessageHandler messageHandler, Action onClose); /// /// Listen to the User Data endpoint. diff --git a/Binance.API.Csharp.Client/BinanceClient.cs b/Binance.API.Csharp.Client/BinanceClient.cs index 18ff5c7..a0f27b2 100644 --- a/Binance.API.Csharp.Client/BinanceClient.cs +++ b/Binance.API.Csharp.Client/BinanceClient.cs @@ -17,7 +17,7 @@ namespace Binance.API.Csharp.Client { public class BinanceClient : BinanceClientAbstract, IBinanceClient - { + { /// /// ctor. /// @@ -261,7 +261,7 @@ public async Task> GetOrderBookTicker() /// Indicates how long an order will remain active before it is executed or expires. /// Specific number of milliseconds the request is valid for. /// - public async Task PostNewOrder(string symbol, decimal quantity, decimal price, OrderSide side, OrderType orderType = OrderType.LIMIT, TimeInForce timeInForce = TimeInForce.GTC, decimal icebergQty = 0m, long recvWindow = 5000) + public async Task PostNewOrder(string symbol, decimal quantity, decimal price, OrderSide side, OrderType orderType = OrderType.LIMIT, TimeInForce timeInForce = TimeInForce.GTC, string clientOrderId = null, decimal icebergQty = 0m, long recvWindow = 5000) { //Validates that the order is valid. ValidateOrderValue(symbol, orderType, price, quantity, icebergQty); @@ -271,8 +271,10 @@ public async Task PostNewOrder(string symbol, decimal quantity, decima + $"&quantity={quantity}" + (orderType == OrderType.LIMIT ? $"&timeInForce={timeInForce}" : "") + (orderType == OrderType.LIMIT ? $"&price={price}" : "") + + (clientOrderId != null ? $"&newClientOrderId={clientOrderId}" : "") + (icebergQty > 0m ? $"&icebergQty={icebergQty}" : "") + $"&recvWindow={recvWindow}"; + var result = await _apiClient.CallAsync(ApiMethod.POST, EndPoints.NewOrder, true, args); return result; @@ -289,18 +291,20 @@ public async Task PostNewOrder(string symbol, decimal quantity, decima /// Indicates how long an order will remain active before it is executed or expires. /// Specific number of milliseconds the request is valid for. /// - public async Task PostNewOrderTest(string symbol, decimal quantity, decimal price, OrderSide side, OrderType orderType = OrderType.LIMIT, TimeInForce timeInForce = TimeInForce.GTC, decimal icebergQty = 0m, long recvWindow = 5000) + public async Task PostNewOrderTest(string symbol, decimal quantity, decimal price, OrderSide side, OrderType orderType = OrderType.LIMIT, TimeInForce timeInForce = TimeInForce.GTC, string clientOrderId = null, decimal icebergQty = 0m, long recvWindow = 5000) { //Validates that the order is valid. ValidateOrderValue(symbol, orderType, price, quantity, icebergQty); //quantity needs to be conform to this regex ^([0-9]{1,20})(\.[0-9]{1,20})?$ -> 20 decimal digits quantity = decimal.Round(quantity, 20); var args = $"symbol={symbol.ToUpper()}&side={side}&type={orderType}" - + $"&quantity={quantity}" //quantity needs to be conform to this regex ^([0-9]{1,20})(\.[0-9]{1,20})?$ - + (orderType == OrderType.LIMIT ? $"&timeInForce={timeInForce}" : "") - + (orderType == OrderType.LIMIT ? $"&price={price}" : "") - + (icebergQty > 0m ? $"&icebergQty={icebergQty}" : "") - + $"&recvWindow={recvWindow}"; + + $"&quantity={quantity}" + + (orderType == OrderType.LIMIT ? $"&timeInForce={timeInForce}" : "") + + (orderType == OrderType.LIMIT ? $"&price={price}" : "") + + (clientOrderId != null ? $"&newClientOrderId ={clientOrderId}" : "") + + (icebergQty > 0m ? $"&icebergQty={icebergQty}" : "") + + $"&recvWindow={recvWindow}"; + var result = await _apiClient.CallAsync(ApiMethod.POST, EndPoints.NewOrderTest, true, args); return result; From 3c397f839dd4d70e58f275bf5e5b5fa312cd675b Mon Sep 17 00:00:00 2001 From: "F.Buldo" Date: Sat, 3 Feb 2018 21:34:38 +0100 Subject: [PATCH 19/21] fix: remove trailing zeros --- Binance.API.Csharp.Client/BinanceClient.cs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/Binance.API.Csharp.Client/BinanceClient.cs b/Binance.API.Csharp.Client/BinanceClient.cs index a0f27b2..b1b95ee 100644 --- a/Binance.API.Csharp.Client/BinanceClient.cs +++ b/Binance.API.Csharp.Client/BinanceClient.cs @@ -266,7 +266,9 @@ public async Task PostNewOrder(string symbol, decimal quantity, decima //Validates that the order is valid. ValidateOrderValue(symbol, orderType, price, quantity, icebergQty); //quantity needs to be conform to this regex ^([0-9]{1,20})(\.[0-9]{1,20})?$ -> 20 decimal digits - quantity = decimal.Round(quantity, 20); + //remove trailing zeros from quantity and price + quantity = quantity / 1.000000000000000000000000000000m; + price = price / 1.000000000000000000000000000000m; var args = $"symbol={symbol.ToUpper()}&side={side}&type={orderType}" + $"&quantity={quantity}" + (orderType == OrderType.LIMIT ? $"&timeInForce={timeInForce}" : "") @@ -274,7 +276,7 @@ public async Task PostNewOrder(string symbol, decimal quantity, decima + (clientOrderId != null ? $"&newClientOrderId={clientOrderId}" : "") + (icebergQty > 0m ? $"&icebergQty={icebergQty}" : "") + $"&recvWindow={recvWindow}"; - + var result = await _apiClient.CallAsync(ApiMethod.POST, EndPoints.NewOrder, true, args); return result; @@ -296,7 +298,8 @@ public async Task PostNewOrderTest(string symbol, decimal quantity, dec //Validates that the order is valid. ValidateOrderValue(symbol, orderType, price, quantity, icebergQty); //quantity needs to be conform to this regex ^([0-9]{1,20})(\.[0-9]{1,20})?$ -> 20 decimal digits - quantity = decimal.Round(quantity, 20); + quantity = quantity / 1.000000000000000000000000000000m; + price = price / 1.000000000000000000000000000000m; var args = $"symbol={symbol.ToUpper()}&side={side}&type={orderType}" + $"&quantity={quantity}" + (orderType == OrderType.LIMIT ? $"&timeInForce={timeInForce}" : "") @@ -386,14 +389,12 @@ public async Task CancelOrder(string symbol, long? orderId = null /// Ticker symbol. /// Specific number of milliseconds the request is valid for. /// - public async Task> GetCurrentOpenOrders(string symbol, long recvWindow = 5000) + public async Task> GetCurrentOpenOrders(string symbol = null, long recvWindow = 5000) { - if (string.IsNullOrWhiteSpace(symbol)) - { - throw new ArgumentException("symbol cannot be empty. ", "symbol"); - } - var result = await _apiClient.CallAsync>(ApiMethod.GET, EndPoints.CurrentOpenOrders, true, $"symbol={symbol.ToUpper()}&recvWindow={recvWindow}"); + var args = $"recvWindow={recvWindow}" + + (!string.IsNullOrEmpty(symbol) ? $"&symbol={symbol.ToUpper()}" : ""); + var result = await _apiClient.CallAsync>(ApiMethod.GET, EndPoints.CurrentOpenOrders, true, args); return result; } From 55fd0d4c9e396629d9b32c70474d7342ccf43347 Mon Sep 17 00:00:00 2001 From: "F.Buldo" Date: Tue, 20 Feb 2018 09:17:18 +0100 Subject: [PATCH 20/21] added missing parameters to GetTradeList --- .../Abstract/ApiClientAbstract.cs | 2 +- .../Interfaces/IBinanceClient.cs | 2 +- Binance.API.Csharp.Client/ApiClient.cs | 2 +- Binance.API.Csharp.Client/BinanceClient.cs | 22 ++++++++++++++++--- 4 files changed, 22 insertions(+), 6 deletions(-) diff --git a/Binance.API.Csharp.Client.Domain/Abstract/ApiClientAbstract.cs b/Binance.API.Csharp.Client.Domain/Abstract/ApiClientAbstract.cs index 03868dd..a0c0c60 100644 --- a/Binance.API.Csharp.Client.Domain/Abstract/ApiClientAbstract.cs +++ b/Binance.API.Csharp.Client.Domain/Abstract/ApiClientAbstract.cs @@ -50,7 +50,7 @@ public abstract class ApiClientAbstract /// Key used to authenticate within the API. /// API secret used to signed API calls. /// API based url. - public ApiClientAbstract(string apiKey, string apiSecret, string apiUrl = @"https://www.binance.com", string webSocketEndpoint = @"wss://stream.binance.com:9443/ws/", bool addDefaultHeaders = true) + public ApiClientAbstract(string apiKey, string apiSecret, string apiUrl = @"https://us.binance.com", string webSocketEndpoint = @"wss://stream.binance.com:9443/ws/", bool addDefaultHeaders = true) { _apiUrl = apiUrl; _apiKey = apiKey; diff --git a/Binance.API.Csharp.Client.Domain/Interfaces/IBinanceClient.cs b/Binance.API.Csharp.Client.Domain/Interfaces/IBinanceClient.cs index 3a2c0d0..a33f67c 100644 --- a/Binance.API.Csharp.Client.Domain/Interfaces/IBinanceClient.cs +++ b/Binance.API.Csharp.Client.Domain/Interfaces/IBinanceClient.cs @@ -150,7 +150,7 @@ public interface IBinanceClient /// Ticker symbol. /// Specific number of milliseconds the request is valid for. /// - Task> GetTradeList(string symbol, long recvWindow = 6000000); + Task> GetTradeList(string symbol, int limit, long fromId, long recvWindow = 5000); /// /// Submit a withdraw request. diff --git a/Binance.API.Csharp.Client/ApiClient.cs b/Binance.API.Csharp.Client/ApiClient.cs index 831f2ef..856a8f2 100644 --- a/Binance.API.Csharp.Client/ApiClient.cs +++ b/Binance.API.Csharp.Client/ApiClient.cs @@ -22,7 +22,7 @@ public class ApiClient : ApiClientAbstract, IApiClient /// Key used to authenticate within the API. /// API secret used to signed API calls. /// API base url. - public ApiClient(string apiKey, string apiSecret, string apiUrl = @"https://www.binance.com", string webSocketEndpoint = @"wss://stream.binance.com:9443/ws/", bool addDefaultHeaders = true) : base(apiKey, apiSecret, apiUrl, webSocketEndpoint, addDefaultHeaders) + public ApiClient(string apiKey, string apiSecret, string apiUrl = @"https://us.binance.com", string webSocketEndpoint = @"wss://stream.binance.com:9443/ws/", bool addDefaultHeaders = true) : base(apiKey, apiSecret, apiUrl, webSocketEndpoint, addDefaultHeaders) { } diff --git a/Binance.API.Csharp.Client/BinanceClient.cs b/Binance.API.Csharp.Client/BinanceClient.cs index b1b95ee..b204c71 100644 --- a/Binance.API.Csharp.Client/BinanceClient.cs +++ b/Binance.API.Csharp.Client/BinanceClient.cs @@ -437,18 +437,34 @@ public async Task GetAccountInfo(long recvWindow = 5000) /// Ticker symbol. /// Specific number of milliseconds the request is valid for. /// - public async Task> GetTradeList(string symbol, long recvWindow = 5000) + public async Task> GetTradeList(string symbol, int limit, long fromId, long recvWindow = 5000) { if (string.IsNullOrWhiteSpace(symbol)) { throw new ArgumentException("symbol cannot be empty. ", "symbol"); } - - var result = await _apiClient.CallAsync>(ApiMethod.GET, EndPoints.TradeList, true, $"symbol={symbol.ToUpper()}&recvWindow={recvWindow}"); + var para = $"symbol={symbol.ToUpper()}&limit={limit}&fromId={fromId}&recvWindow={recvWindow}"; + var result = await _apiClient.CallAsync>(ApiMethod.GET, EndPoints.TradeList, true, para); return result; } + /// + /// Get trades for a specific account and symbol. + /// + /// Ticker symbol. + /// Specific number of milliseconds the request is valid for. + /// + public async Task> GetTradeList(string symbol, int limit, long recvWindow = 5000) + { + if (string.IsNullOrWhiteSpace(symbol)) + { + throw new ArgumentException("symbol cannot be empty. ", "symbol"); + } + var para = $"symbol={symbol.ToUpper()}&limit={limit}&recvWindow={recvWindow}"; + var result = await _apiClient.CallAsync>(ApiMethod.GET, EndPoints.TradeList, true, para); + return result; + } /// /// Submit a withdraw request. /// From 568e20b28a68d0c645a9c638c445c7f0d183a2cd Mon Sep 17 00:00:00 2001 From: "F.Buldo" Date: Sun, 25 Feb 2018 23:23:00 +0100 Subject: [PATCH 21/21] fix trade info --- Binance.API.Csharp.Client.Models/Account/Trade.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Binance.API.Csharp.Client.Models/Account/Trade.cs b/Binance.API.Csharp.Client.Models/Account/Trade.cs index f01c9fd..bec3ddb 100644 --- a/Binance.API.Csharp.Client.Models/Account/Trade.cs +++ b/Binance.API.Csharp.Client.Models/Account/Trade.cs @@ -6,6 +6,8 @@ public class Trade { [JsonProperty("id")] public int Id { get; set; } + [JsonProperty("orderId")] + public int OrderId { get; set; } [JsonProperty("price")] public decimal Price { get; set; } [JsonProperty("qty")]