From bdcde28f0386f551d77fe21fcd16cd7016a5d67c Mon Sep 17 00:00:00 2001 From: Victor Lee Date: Sat, 19 Feb 2022 20:37:04 -0800 Subject: [PATCH] add trade stream to LBank - added ability to parse china time zone --- .../API/Exchanges/LBank/ExchangeLBankAPI.cs | 59 +++++++++++++++++++ src/ExchangeSharp/Utility/CryptoUtility.cs | 14 ++++- 2 files changed, 72 insertions(+), 1 deletion(-) diff --git a/src/ExchangeSharp/API/Exchanges/LBank/ExchangeLBankAPI.cs b/src/ExchangeSharp/API/Exchanges/LBank/ExchangeLBankAPI.cs index 8a609fbd..86376aad 100644 --- a/src/ExchangeSharp/API/Exchanges/LBank/ExchangeLBankAPI.cs +++ b/src/ExchangeSharp/API/Exchanges/LBank/ExchangeLBankAPI.cs @@ -39,6 +39,8 @@ public class ExchangeLBankAPI : ExchangeAPI /// public override string BaseUrl { get; set; } = "https://api.lbank.info/v1"; + public override string BaseUrlWebSocket { get; set; } = "wss://www.lbkex.net/ws/V2/"; + /// /// Gets the name of the API. /// @@ -539,6 +541,63 @@ private List ParseWithdrawListResponse(JToken withdr #endregion PARSERS PrivateAPI + #region Websockets + protected override async Task OnGetTradesWebSocketAsync(Func, Task> callback, params string[] marketSymbols) + { + if (marketSymbols == null || marketSymbols.Length == 0) + { + marketSymbols = (await GetMarketSymbolsAsync()).ToArray(); + } + return await ConnectPublicWebSocketAsync("", async (_socket, msg) => + { + /* { + "trade":{ + "volume":6.3607, + "amount":77148.9303, + "price":12129, + "direction":"sell", + "TS":"2019-06-28T19:55:49.460" + }, + "type":"trade", + "pair":"btc_usdt", + "SERVER":"V2", + "TS":"2019-06-28T19:55:49.466" + }*/ + JToken token = JToken.Parse(msg.ToStringFromUTF8()); + if (token["status"].ToStringInvariant() == "error") + { + if (token["message"].ToStringInvariant().Contains("Invalid order pairs")) + { + // ignore, bc invalid order pairs are normal in LBank + } + else throw new APIException(token["message"].ToStringInvariant()); + } + else if (token["type"].ToStringInvariant() == "trade") + { + var trade = token["trade"].ParseTrade("amount", "price", "direction", "TS", TimestampType.Iso8601China, null); + string marketSymbol = token["pair"].ToStringInvariant(); + await callback(new KeyValuePair(marketSymbol, trade)); + } + }, async (_socket) => + { /* { + "action":"subscribe", + "subscribe":"trade", + "pair":"eth_btc" + }*/ + foreach (var marketSymbol in marketSymbols) + { + var subscribeRequest = new + { + action = "subscribe", + subscribe = "trade", + pair = marketSymbol, + }; + await _socket.SendMessageAsync(subscribeRequest); + } + }); + } + #endregion + #region HELPERS protected override async Task ProcessRequestAsync(IHttpWebRequest request, Dictionary payload) diff --git a/src/ExchangeSharp/Utility/CryptoUtility.cs b/src/ExchangeSharp/Utility/CryptoUtility.cs index 18beda23..6b968352 100644 --- a/src/ExchangeSharp/Utility/CryptoUtility.cs +++ b/src/ExchangeSharp/Utility/CryptoUtility.cs @@ -38,6 +38,8 @@ public static class CryptoUtility internal static readonly DateTime UnixEpochLocal = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Local); internal static readonly Encoding Utf8EncodingNoPrefix = new UTF8Encoding(false, true); static bool isWindows = System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(OSPlatform.Windows); + static string chinaZoneId = isWindows ? "China Standard Time" : "Asia/Shanghai"; + static TimeZoneInfo chinaZone = TimeZoneInfo.FindSystemTimeZoneById(chinaZoneId); static string koreanZoneId = isWindows ? "Korea Standard Time" : "Asia/Seoul"; static TimeZoneInfo koreaZone = TimeZoneInfo.FindSystemTimeZoneById(koreanZoneId); @@ -188,7 +190,7 @@ public enum SourceTimeZone { /// time zone is specifically specified in string AsSpecified, - Local, Korea, UTC + Local, China, Korea, UTC, } /// /// Convert object to a UTC DateTime @@ -215,6 +217,8 @@ public static DateTime ToDateTimeInvariant(this object obj, SourceTimeZone sourc throw new NotImplementedException(); // TODO: implement this when needed case SourceTimeZone.Local: return DateTime.SpecifyKind(dt, DateTimeKind.Local).ToUniversalTime(); // convert to UTC + case SourceTimeZone.China: + return TimeZoneInfo.ConvertTime(dt, chinaZone, TimeZoneInfo.Utc); // convert to UTC case SourceTimeZone.Korea: return TimeZoneInfo.ConvertTime(dt, koreaZone, TimeZoneInfo.Utc); // convert to UTC case SourceTimeZone.UTC: @@ -693,6 +697,9 @@ public static DateTime ParseTimestamp(object value, TimestampType type) case TimestampType.Iso8601Local: return value.ToDateTimeInvariant(SourceTimeZone.Local); + case TimestampType.Iso8601China: + return value.ToDateTimeInvariant(SourceTimeZone.China); + case TimestampType.Iso8601Korea: return value.ToDateTimeInvariant(SourceTimeZone.Korea); @@ -1481,6 +1488,11 @@ public enum TimestampType /// Iso8601Local, + /// + /// ISO 8601 in china Standard Time + /// + Iso8601China, + /// /// ISO 8601 in Korea Standard Time ///