Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add connector for Mexc spot broker #767

Merged
merged 1 commit into from
Dec 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions project/OsEngine/Market/ServerMaster.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
using OsEngine.Market.Servers.MoexFixFastCurrency;
using OsEngine.Market.Servers.MoexFixFastTwimeFutures;
using OsEngine.Market.Servers.TraderNet;
using OsEngine.Market.Servers.Mexc;

namespace OsEngine.Market
{
Expand Down Expand Up @@ -213,6 +214,7 @@ public static List<ServerType> ServersTypes
serverTypes.Add(ServerType.MoexFixFastCurrency);
serverTypes.Add(ServerType.MoexFixFastTwimeFutures);
serverTypes.Add(ServerType.TraderNet);
serverTypes.Add(ServerType.Mexc);

serverTypes.Add(ServerType.AstsBridge);

Expand Down Expand Up @@ -604,6 +606,10 @@ public static void CreateServer(ServerType type, bool neadLoadTicks)
{
newServer = new TraderNetServer();
}
else if (type == ServerType.Mexc)
{
newServer = new MexcServer();
}

if (newServer == null)
{
Expand Down Expand Up @@ -1216,6 +1222,10 @@ public static IServerPermission GetServerPermission(ServerType type)
{
serverPermission = new TraderNetServerPermission();
}
else if (type == ServerType.Mexc)
{
serverPermission = new MexcServerPermission();
}

if (serverPermission != null)
{
Expand Down Expand Up @@ -1664,5 +1674,10 @@ public enum ServerType
/// TraderNet
/// </summary>
TraderNet,

/// <summary>
/// Mexc Spot
/// </summary>
Mexc,
}
}
153 changes: 153 additions & 0 deletions project/OsEngine/Market/Servers/Mexc/Entity/MexcClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
using OsEngine.Market.Servers.Entity;
using System;
using System.Net.Http;
using System.Text;
using System.Security.Cryptography;
using Google.Protobuf.WellKnownTypes;
using System.Collections.Generic;
using OsEngine.Market.Services;
using System.Windows.Input;

namespace OsEngine.Market.Servers.Mexc.Json
{

public class MexcRestClient
{
private readonly string _restApiHost = "https://api.mexc.com";

private string _apiKey;
private string _apiSecret;


private HttpClient _client = new HttpClient();

//rate limiter
public RateGate _rateGateRest = new RateGate(1, TimeSpan.FromMilliseconds(30));


// https://mexcdevelop.github.io/apidocs/spot_v3_en/#signed

public MexcRestClient(string apiKey, string apiSecret)
{
this._apiKey = apiKey;
this._apiSecret = apiSecret;
}

private string GetQueryString(Dictionary<string, string> queryParams = null)
{
string query = "";

if (queryParams != null)
{
foreach (var onePar in queryParams)
{
if (query.Length > 0)
query += "&";
query += onePar.Key + "=" + onePar.Value;
}
}

return query;
}

private string GetSecuredQueryString(Dictionary<string, string> queryParams = null)
{
string query = GetQueryString(queryParams);

string timestamp = GetTimestamp();

if (query.Length > 0)
query += "&";

query += "recvWindow=10000&timestamp=" + timestamp;

string signature = GenerateSignature(query, _apiSecret);

query += "&signature=" + signature;

return query;

}
public HttpResponseMessage Post(string endPoint, Dictionary<string, string> queryParams = null, bool secured = false)
{
return this.Query(HttpMethod.Post, endPoint, queryParams, secured);
}

public HttpResponseMessage Put(string endPoint, Dictionary<string, string> queryParams = null, bool secured = false)
{
return this.Query(HttpMethod.Put, endPoint, queryParams, secured);
}

public HttpResponseMessage Get(string endPoint, Dictionary<string, string> queryParams = null, bool secured = false)
{
return this.Query(HttpMethod.Get, endPoint, queryParams, secured);
}

public HttpResponseMessage Delete(string endPoint, Dictionary<string, string> queryParams = null, bool secured = false)
{
return this.Query(HttpMethod.Delete, endPoint, queryParams, secured);
}


private HttpResponseMessage Query(HttpMethod method, string endPoint, Dictionary<string, string> queryParams = null, bool secured = false)
{
_rateGateRest.WaitToProceed();

HttpRequestMessage request = null;

if (secured)
{
string query = GetSecuredQueryString(queryParams);

string url = _restApiHost + endPoint;
if (!string.IsNullOrEmpty(query))
{
url += "?" + query;
}

request = new HttpRequestMessage(method, url);
request.Headers.Add("X-MEXC-APIKEY", this._apiKey);
}
else
{
string query = GetQueryString(queryParams);

string url = _restApiHost + endPoint;
if (!string.IsNullOrEmpty(query))
{
url += "?" + query;
}
request = new HttpRequestMessage(method, url);
}

HttpResponseMessage response = _client.SendAsync(request).Result;

return response;
}

/// <summary>
/// take milisecond time from 01.01.1970
/// взять время в милисекундах, прошедшее с 1970, 1, 1 года
/// </summary>
/// <returns></returns>
public static string GetTimestamp()
{
return DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString();
}

public static string GenerateSignature(string source, string key)
{
byte[] keyBytes = Encoding.UTF8.GetBytes(key);
using (HMACSHA256 hmacsha256 = new HMACSHA256(keyBytes))
{
byte[] sourceBytes = Encoding.UTF8.GetBytes(source);

byte[] hash = hmacsha256.ComputeHash(sourceBytes);

return BitConverter.ToString(hash).Replace("-", "").ToLower();
}
}

}

}
150 changes: 150 additions & 0 deletions project/OsEngine/Market/Servers/Mexc/Entity/MexcOrdersRest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
/*
*Your rights to use the code are governed by this license https://github.com/AlexWan/OsEngine/blob/master/LICENSE
*Ваши права на использование кода регулируются данной лицензией http://o-s-a.net/doc/license_simple_engine.pdf
*/

using Newtonsoft.Json;
using System.Collections.Generic;
using System.Windows.Forms;

namespace OsEngine.Market.Servers.Mexc.Json
{

public class MexcTrade
{
public string symbol { get; set; }
public string id { get; set; }
public string orderId { get; set; }
public int orderListId { get; set; }
public string price { get; set; }
public string qty { get; set; }
public string quoteQty { get; set; }
public string commission { get; set; }
public string commissionAsset { get; set; }
public long time { get; set; }
public bool isBuyer { get; set; }
public bool isMaker { get; set; }
public bool isBestMatch { get; set; }
public bool isSelfTrade { get; set; }
public object clientOrderId { get; set; }
}

public class MexcTrades : List<MexcTrade>
{

}


public class MexcOrder
{
public string symbol { get; set; }
public string side { get; set; }
public string type { get; set; }
public string notional { get; set; }
public string size { get; set; }
public string ms_t { get; set; }
public string price { get; set; }
public string filled_notional { get; set; }
public string filled_size { get; set; }
public string margin_trading { get; set; }
public string state { get; set; }
public string order_id { get; set; }
public string order_type { get; set; }
public string last_fill_time { get; set; }
public string last_fill_price { get; set; }
public string last_fill_count { get; set; }
public string exec_type { get; set; }
public string detail_id { get; set; }
public string client_order_id { get; set; }
public string create_time { get; set; }
public string update_time { get; set; }
public string order_mode { get; set; }
public string entrust_type { get; set; }
public string order_state { get; set; }
}

public class MexcOrders : List<MexcOrder>
{

}

public class MexcRestOrder
{
public string orderId { get; set; }
public string clientOrderId { get; set; }
public string symbol { get; set; }
public string side { get; set; }
public string orderMode { get; set; }
public string type { get; set; }
public string state { get; set; }
public string price { get; set; }
public string priceAvg { get; set; }
public string size { get; set; }
public string filledSize { get; set; }
public string notional { get; set; }
public string filledNotional { get; set; }
public long createTime { get; set; }
public long updateTime { get; set; }
}

public class MexcRestOrders : List<MexcRestOrder>
{

}

public class MexcRestOrdersBaseMessage
{
public int code;
public string trace;
public string message;
public object data;
}

public class MexcNewOrderResponse
{
public string symbol { get; set; }
public string orderId { get; set; }
public int orderListId { get; set; }
public string price { get; set; }
public string origQty { get; set; }
public string type { get; set; }
public string side { get; set; }
public long transactTime { get; set; }
}

public class MexcOrderResponse
{
public string symbol { get; set; }
public string origClientOrderId { get; set; }
public string orderId { get; set; }
public string clientOrderId { get; set; }
public string price { get; set; }
public string origQty { get; set; }
public string executedQty { get; set; }
public string cummulativeQuoteQty { get; set; }
public string status { get; set; }
public string timeInForce { get; set; }
public string type { get; set; }
public string side { get; set; }

public string stopPrice { get; set; }
public string icebergQty { get; set; }
public ulong time { get; set; }
public object updateTime { get; set; }
public bool isWorking { get; set; }
public string origQuoteOrderQty { get; set; }

}

public class MexcOrderListResponse : List<MexcOrderResponse>
{

}

public class MexcDefaultSymbols
{
public int code { get; set; }
public List<string> data { get; set; }
public string msg { get; set; }
}
}
29 changes: 29 additions & 0 deletions project/OsEngine/Market/Servers/Mexc/Entity/MexcPortfolioRest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
*Your rights to use the code are governed by this license https://github.com/AlexWan/OsEngine/blob/master/LICENSE
*Ваши права на использование кода регулируются данной лицензией http://o-s-a.net/doc/license_simple_engine.pdf
*/

using System.Collections.Generic;

namespace OsEngine.Market.Servers.Mexc.Json
{

public class MexcBalance
{
public string asset { get; set; }
public string free { get; set; }
public string locked { get; set; }
}

public class MexcPortfolioRest
{
public bool canTrade { get; set; }
public bool canWithdraw { get; set; }
public bool canDeposit { get; set; }
public object updateTime { get; set; }
public string accountType { get; set; }
public List<MexcBalance> balances { get; set; }
public List<string> permissions { get; set; }
}

}
Loading