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
///