336 lines
14 KiB
C#
336 lines
14 KiB
C#
using BitgetAPI;
|
|
using BitgetAPI.Utils;
|
|
using BitgetAPI.Data;
|
|
using BitgetAPI.Utils;
|
|
using Newtonsoft.Json;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Net;
|
|
using System.Net.WebSockets;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using BitgetApi.Data;
|
|
using Newtonsoft.Json.Linq;
|
|
using DevExpress.Utils.Extensions;
|
|
|
|
namespace BitgetAPI.WebService
|
|
{
|
|
public class WebConnection
|
|
{
|
|
public static object SendWebServer(CommonProperty.ExchangeWebReqType exchangeWebReqType, string url = "", string postData = "", string subUri = "")
|
|
{
|
|
object returnJsonData = null;
|
|
|
|
CommonProperty commonProperty = CommonProperty.Instance;
|
|
|
|
try
|
|
{
|
|
HttpWebRequest wReq = null;
|
|
|
|
// Post 방식인 경우만 사용
|
|
var rgbyData = Encoding.ASCII.GetBytes(postData);
|
|
|
|
// 웹 전송 타입 지정
|
|
var webConType = CommonProperty.WebConnectionType.GET;
|
|
|
|
// 1. WebRequest 객체 형성 및 HttpWebRequest 로 형변환
|
|
// 2. 거래소에 따른 헤더 파일 처리(POST 일 경우만 지정함)
|
|
|
|
|
|
if(string.IsNullOrEmpty(url))
|
|
{
|
|
switch (exchangeWebReqType)
|
|
{
|
|
#region Upbit
|
|
case CommonProperty.ExchangeWebReqType.UpbitMarket:
|
|
wReq = (HttpWebRequest)WebRequest.Create(new Uri(CommonProperty.UpbitURL_MarketInfo));
|
|
break;
|
|
#endregion
|
|
|
|
#region Bitget
|
|
case CommonProperty.ExchangeWebReqType.BitgetMarket_Spot:
|
|
wReq = (HttpWebRequest)WebRequest.Create(new Uri(CommonProperty.BitgetURL_MarketInfo_COIN));
|
|
break;
|
|
|
|
case CommonProperty.ExchangeWebReqType.BitgetMarket_Future:
|
|
wReq = (HttpWebRequest)WebRequest.Create(new Uri(CommonProperty.BitgetURL_MarketInfo_FUTURE));
|
|
break;
|
|
|
|
case CommonProperty.ExchangeWebReqType.BitgetCandleStick_Coin:
|
|
wReq = (HttpWebRequest)WebRequest.Create(new Uri(CommonProperty.BitgetURL_MarketCandle_Coin));
|
|
break;
|
|
case CommonProperty.ExchangeWebReqType.BitgetCandleStick_Future:
|
|
wReq = (HttpWebRequest)WebRequest.Create(new Uri(CommonProperty.BitgetURL_MarketCandle_Future));
|
|
break;
|
|
#endregion
|
|
|
|
}
|
|
}
|
|
else wReq= (HttpWebRequest)WebRequest.Create(new Uri(url));
|
|
|
|
|
|
// GET, POST 구분
|
|
switch (webConType)
|
|
{
|
|
case CommonProperty.WebConnectionType.GET:
|
|
break;
|
|
case CommonProperty.WebConnectionType.POST:
|
|
wReq.Method = "POST"; // 전송 방법 "GET" or "POST"
|
|
using (var stream = wReq.GetRequestStream())
|
|
{
|
|
stream.Write(rgbyData, 0, rgbyData.Length);
|
|
}
|
|
wReq.ContentType = "application/x-www-form-urlencoded";
|
|
wReq.ContentLength = rgbyData.Length;
|
|
break;
|
|
}
|
|
|
|
using (var wRes = (HttpWebResponse)wReq.GetResponse())
|
|
{
|
|
var respPostStream = wRes.GetResponseStream();
|
|
var readerPost = new StreamReader(respPostStream, Encoding.UTF8, true);
|
|
var resResult = readerPost.ReadToEnd();
|
|
switch (exchangeWebReqType)
|
|
{
|
|
#region Bitget
|
|
case CommonProperty.ExchangeWebReqType.BitgetMarket_Spot:
|
|
{
|
|
var datalist = JsonConvert.DeserializeObject<Dictionary<string, object>>(resResult);
|
|
var marketInfo = JsonConvert.DeserializeObject<List<Dictionary<string, object>>>(datalist["data"]?.ToString());
|
|
var data = marketInfo.FindAll(x => x["coin"].ToString().Contains("USDT"));
|
|
}
|
|
break;
|
|
case CommonProperty.ExchangeWebReqType.BitgetMarket_Future:
|
|
{
|
|
var datalist = JsonConvert.DeserializeObject<Dictionary<string, object>>(resResult);
|
|
var marketInfos = JsonConvert.DeserializeObject<List<Dictionary<string, object>>>(datalist["data"]?.ToString());
|
|
|
|
commonProperty.marketInfoList = new List<MarketInfo>();
|
|
|
|
foreach (var item in marketInfos)
|
|
{
|
|
MarketInfo marketInfo = new MarketInfo();
|
|
marketInfo.MarketName = item["symbol"].ToString();
|
|
marketInfo.ExchangePlace = Enum.GetName(typeof(CommonProperty.ExchangePlace), commonProperty.selectedChangePlace);
|
|
commonProperty.marketInfoList.Add(marketInfo);
|
|
}
|
|
|
|
return commonProperty.marketInfoList;
|
|
}
|
|
break;
|
|
case CommonProperty.ExchangeWebReqType.BitgetCandleStick_Coin:
|
|
{
|
|
|
|
}
|
|
break;
|
|
case CommonProperty.ExchangeWebReqType.BitgetCandleStick_Future:
|
|
{
|
|
var datalist = JsonConvert.DeserializeObject<Dictionary<string, object>>(resResult);
|
|
var datas = JsonConvert.DeserializeObject<List<List<object>>>(datalist["data"]?.ToString());
|
|
|
|
List<CandleData> candleDatas = new List<CandleData>();
|
|
|
|
foreach(var item in datas)
|
|
{
|
|
CandleData candleData = new CandleData();
|
|
candleData.Argument = Convertor.GetUnixtimeStampToDateTime(long.Parse(item[0].ToString()));
|
|
candleData.Open = Convert.ToDouble(item[1]);
|
|
candleData.High = Convert.ToDouble(item[2]);
|
|
candleData.Low = Convert.ToDouble(item[3]);
|
|
candleData.Close = Convert.ToDouble(item[4]);
|
|
candleData.Vol_C = Convert.ToDouble(item[5]);
|
|
candleData.Vol_USD = Convert.ToDouble(item[6]);
|
|
|
|
candleDatas.Add(candleData);
|
|
}
|
|
|
|
return candleDatas;
|
|
}
|
|
break;
|
|
#endregion
|
|
}
|
|
}
|
|
}
|
|
catch (WebException webEx)
|
|
{
|
|
using (var Response = (HttpWebResponse)webEx.Response)
|
|
{
|
|
var nCode = Response.StatusCode;
|
|
|
|
using (var reader = new StreamReader(Response.GetResponseStream()))
|
|
{
|
|
var sRespBodyData = reader.ReadToEnd();
|
|
|
|
//return (JObject.Parse(sRespBodyData));
|
|
}
|
|
}
|
|
}
|
|
|
|
return returnJsonData;
|
|
}
|
|
|
|
public async void webSocektStart()
|
|
{
|
|
string apiUrl = "https://api.upbit.com/v1/market/all?isDetails=true";
|
|
|
|
// IP당 100개 연결
|
|
// 시간당 240회 !!!
|
|
// 타이머 30초 유지 > 30초 이내의 응답 메시지 수신 필요 > 아니면 오류 발생 !! > 재접속 필요 !!
|
|
// 초당 10개 메시지 허용
|
|
// 단일 연결로 최대 1000개의 스트림 구독
|
|
// 단인 IP 최대의 100개 연결
|
|
|
|
// *
|
|
/* timestamp : Unix Epoch 시간
|
|
* passphrase : APIKey 비밀번호
|
|
* timestamp : Unix Epoch 시간, 단위는 초(--restAPI의 서명 타임스탬프와 다름--)
|
|
* secretKey : 사용자가 APIKey를 신청할 때 생성되는 보안 키입니다. 예: 22582BD0CFF14C41EDBF1AB98506286D
|
|
*/
|
|
|
|
ClientWebSocket webSocket = new ClientWebSocket();
|
|
|
|
string WebSocketUrl = "wss://ws.bitget.com/v2/ws/public";
|
|
string message = "";
|
|
var tempStrData = "";
|
|
|
|
CommonProperty commonProperty = CommonProperty.Instance;
|
|
|
|
try
|
|
{
|
|
await webSocket.ConnectAsync(new Uri(WebSocketUrl), CancellationToken.None);
|
|
// 연결이 성공적으로 이루어지면 처리할 코드 작성
|
|
Console.WriteLine("WebSocket 연결 성공");
|
|
|
|
// Json String 만들기
|
|
// 종목별 Ticker 구독하기
|
|
var dic = new Dictionary<string, object>();
|
|
dic.Add("op", "subscribe");
|
|
|
|
var argsList = new List<Dictionary<string, object>>();
|
|
foreach (var marketInfo in commonProperty.marketInfoList)
|
|
{
|
|
var args = new Dictionary<string, object>();
|
|
args.Add("instType", "USDT-FUTURES");
|
|
args.Add("channel", "ticker");
|
|
//args.Add("channel", "candle1m");
|
|
args.Add("instId", marketInfo.MarketName);
|
|
argsList.Add(args);
|
|
}
|
|
dic.Add("args", argsList);
|
|
|
|
//var jsonDataText = "{\"op\":\"subscribe\",\"args\":[{\"instType\":\"SPOT\",\"channel\":\"ticker\",\"instId\":\"ETHUSDT\"}, {\"instType\":\"SPOT\",\"channel\":\"ticker\",\"instId\":\"BTCUSDT\"}]}";
|
|
|
|
var jsonData = JsonConvert.SerializeObject(dic);
|
|
|
|
await SendMessage(webSocket, jsonData);
|
|
|
|
|
|
// 데이터 수신을 위한 반복문 시작
|
|
while (webSocket.State == WebSocketState.Open)
|
|
{
|
|
//Thread.Sleep(100);
|
|
|
|
byte[] buffer = new byte[1024];
|
|
WebSocketReceiveResult result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
|
|
message = "";
|
|
// 수신한 데이터 처리
|
|
message = System.Text.Encoding.UTF8.GetString(buffer, 0, result.Count);
|
|
|
|
if (!ValidateJSON(message))
|
|
{
|
|
tempStrData += message;
|
|
if (!ValidateJSON(message))
|
|
{
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
message = tempStrData;
|
|
}
|
|
}
|
|
var datalist = JsonConvert.DeserializeObject<Dictionary<string, object>>(message);
|
|
|
|
if (datalist.ContainsKey("data"))
|
|
{
|
|
var candleInfo = JsonConvert.DeserializeObject<List<WebSocketCandle>>(datalist["data"]?.ToString());
|
|
|
|
var tickerList = candleInfo[0];
|
|
|
|
DateTime dt = new DateTime(1970, 01, 01);
|
|
tickerList.reciveTime = dt.AddMilliseconds(Convert.ToDouble(tickerList.ts)).ToLocalTime();
|
|
|
|
var searchIndex = commonProperty.webSocketCandles.IndexOf(i => i.instId == tickerList.instId);
|
|
if (searchIndex < 0)
|
|
commonProperty.webSocketCandles.Add(tickerList);
|
|
else
|
|
{
|
|
commonProperty.webSocketCandles[searchIndex] = tickerList;
|
|
}
|
|
|
|
//var sendTime = dt.AddMilliseconds(Convert.ToDouble(datalist["ts"])).ToLocalTime();
|
|
|
|
// Candle 리스트에 데이터 쌓기
|
|
//var marketCandleList = commonProperty.candleDataLists.Find(i => i.ConGoodsData.MarketName == candleInfo[0]["instId"].ToString());
|
|
|
|
|
|
// 분 업데이트 (1,3,5,10,15,30)
|
|
//if(recieveTime.Second == 0)
|
|
{
|
|
|
|
}
|
|
// 시 업데이트 (1,4,6)
|
|
//if(recieveTime.Minute == 0)
|
|
{
|
|
|
|
}
|
|
//else
|
|
{
|
|
|
|
}
|
|
|
|
}
|
|
// 요청시간
|
|
|
|
// Candle 시간
|
|
|
|
}
|
|
}
|
|
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine("WebSocket 연결 중 오류 발생: " + ex.Message);
|
|
}
|
|
finally
|
|
{
|
|
if (webSocket.State == WebSocketState.Open)
|
|
await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "WebSocket 연결 종료", CancellationToken.None);
|
|
|
|
webSocket.Dispose();
|
|
}
|
|
}
|
|
|
|
private static async Task SendMessage(ClientWebSocket webSocket, string message)
|
|
{
|
|
byte[] buffer = Encoding.UTF8.GetBytes(message);
|
|
await webSocket.SendAsync(new ArraySegment<byte>(buffer), WebSocketMessageType.Text, true, CancellationToken.None);
|
|
Console.WriteLine("메시지 전송: " + message);
|
|
}
|
|
|
|
public static bool ValidateJSON(string s)
|
|
{
|
|
try
|
|
{
|
|
JToken.Parse(s);
|
|
return true;
|
|
}
|
|
catch (JsonReaderException)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|