using Newtonsoft.Json; using System; using System.Collections.Generic; using WebSocket.Interfaces; using System.Linq; using System.IO; using System.Text; using Newtonsoft.Json.Linq; namespace WebSocket.Clients { public class OKExClient : IWebClient { #region Members internal class OKExResponse { [JsonProperty(PropertyName = "channel")] public string Channel { get; set; } public int Binary { get; set; } public string Pair { get { var arr = this.Channel.Split('_'); if (arr.Length > 4) { return arr[3].ToUpper() + arr[4].ToUpper(); } return string.Empty; } set { } } } internal class OKExResponse2: OKExResponse { [JsonProperty(PropertyName = "data")] public JValue[][] Data { get; set; } } private IWebSocketForClient server; private Dictionary> CommandAnswers = new Dictionary>(); #endregion /// /// ctor /// /// public OKExClient(IWebSocketForClient server) { this.server = server; Register(); } public void Connected() { //SendAuth(); //wait connected message? } public void StartRequest(string[] pairs) { //Send(new [] { new { Event = "addChannel", Channel = $"ok_sub_spot_{pairs[0].ToLower()}_kline_1min" }}); server.Send($"[{{'event':'addChannel','channel':'ok_sub_spot_{pairs[0].ToLower()}_kline_1min'}}]"); } private void Register() { On("connected", (c, obj) => Connected()); On("ping", (c, obj) => SendPong()); //On("ohlcv1m", (c, obj) => Update(c.E, c, obj, typeof(Summary))); } public void Message(string message) { var parse = JsonConvert.DeserializeObject>(message, GetSettings()); var data = parse.FirstOrDefault(); if (data != null) { if (data.Channel.StartsWith("ok_sub_spot")) { dynamic jsonDe = JsonConvert.DeserializeObject(message, GetSettings()); if (jsonDe is JArray && jsonDe.Count > 0) { var rawData = jsonDe[0]; if (rawData != null && rawData.data is JArray) { var parse2 = JsonConvert.DeserializeObject>(message, GetSettings()); var data2 = parse2.FirstOrDefault(); if (data2 != null) { this.server.DataChanged("OKEx", GetMarketOHLCVData(new Dictionary { { data2.Pair, data2 } })); } } } } } } public void Tick() { //'ticker' or 'get-balance' } public void Data(byte[] data) { } public void Data(Dictionary data) { } public void Closed(bool byUser, string reason) { } public void Error(Exception ex) { } public void Error(string reason) { } public void SendFailed(string data, Exception ex) { } private void Send(object obj) { server.Send(JsonConvert.SerializeObject(obj, GetSettings())); } private void SendPong() { Send(new Command() { E = "pong" }); } private void On(string name, Action command) { CommandAnswers[name] = command; } private void Off(string name) { if (CommandAnswers.ContainsKey(name)) { CommandAnswers.Remove(name); } } public Dictionary GetMarketOHLCVData(Dictionary data) { return data.Select(x => { var item = x.Value as OKExResponse2; var itemData = item.Data[0]; if (itemData != null) { //[time, open price, highest price, lowest price, close price, volume] //[string, string, string, string, string, string] return new MarketOHLCVData() { TimeStamp = ConvertFromLong(itemData[0].ToObject()), OpenPrice = itemData[1].ToObject(), HighPrice = itemData[2].ToObject(), LowPrice = itemData[3].ToObject(), ClosePrice = itemData[4].ToObject(), Volume = itemData[5].ToObject(), PairSymbol = x.Key } as IMarketOHLCVData; } else { return null; } }).ToDictionary(x => x.PairSymbol); } #region Helpers private DateTime _1970Time = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); private long ConvertToLong(DateTime time) { return (long)(time - _1970Time).TotalMilliseconds; } private DateTime ConvertFromLong(long ms) { return _1970Time.AddMilliseconds(ms); } private JsonSerializerSettings GetSettings() { var settings = new JsonSerializerSettings() { ContractResolver = new LowerCaseUnderscoreContractResolver() //Formatting = Formatting.Indented }; settings.Converters.Add(new Newtonsoft.Json.Converters.UnixDateTimeConverter()); return settings; } //private static bool IsPropertyExist(dynamic settings, string name) //{ // if (settings is ExpandoObject) // return ((IDictionary)settings).ContainsKey(name); // return settings.GetType().GetProperty(name) != null; //} #endregion } }