mirror of
https://github.com/JKorf/CryptoExchange.Net
synced 2025-06-08 00:16:27 +00:00
Cleaning/docs
This commit is contained in:
parent
60f3696db1
commit
009ae3a45d
@ -8,7 +8,6 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace CryptoExchange.Net
|
namespace CryptoExchange.Net
|
||||||
{
|
{
|
||||||
@ -21,13 +20,14 @@ namespace CryptoExchange.Net
|
|||||||
|
|
||||||
protected static int lastId;
|
protected static int lastId;
|
||||||
protected static object idLock = new object();
|
protected static object idLock = new object();
|
||||||
public static int LastId { get => lastId; }
|
|
||||||
|
|
||||||
private static readonly JsonSerializer defaultSerializer = JsonSerializer.Create(new JsonSerializerSettings()
|
private static readonly JsonSerializer defaultSerializer = JsonSerializer.Create(new JsonSerializerSettings()
|
||||||
{
|
{
|
||||||
DateTimeZoneHandling = DateTimeZoneHandling.Utc
|
DateTimeZoneHandling = DateTimeZoneHandling.Utc
|
||||||
});
|
});
|
||||||
|
|
||||||
|
public static int LastId { get => lastId; }
|
||||||
|
|
||||||
public BaseClient(ExchangeOptions options, AuthenticationProvider authenticationProvider)
|
public BaseClient(ExchangeOptions options, AuthenticationProvider authenticationProvider)
|
||||||
{
|
{
|
||||||
log = new Log();
|
log = new Log();
|
||||||
@ -60,12 +60,27 @@ namespace CryptoExchange.Net
|
|||||||
authProvider = authentictationProvider;
|
authProvider = authentictationProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Deserialize a string into an object
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">The type to deserialize into</typeparam>
|
||||||
|
/// <param name="data">The data to deserialize</param>
|
||||||
|
/// <param name="checkObject">Whether or not the parsing should be checked for missing properties (will output data to the logging if log verbosity is Debug)</param>
|
||||||
|
/// <param name="serializer">A specific serializer to use</param>
|
||||||
|
/// <returns></returns>
|
||||||
protected CallResult<T> Deserialize<T>(string data, bool checkObject = true, JsonSerializer serializer = null)
|
protected CallResult<T> Deserialize<T>(string data, bool checkObject = true, JsonSerializer serializer = null)
|
||||||
{
|
{
|
||||||
var obj = JToken.Parse(data);
|
return Deserialize<T>(JToken.Parse(data), checkObject, serializer);
|
||||||
return Deserialize<T>(obj, checkObject, serializer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Deserialize a JToken into an object
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">The type to deserialize into</typeparam>
|
||||||
|
/// <param name="obj">The data to deserialize</param>
|
||||||
|
/// <param name="checkObject">Whether or not the parsing should be checked for missing properties (will output data to the logging if log verbosity is Debug)</param>
|
||||||
|
/// <param name="serializer">A specific serializer to use</param>
|
||||||
|
/// <returns></returns>
|
||||||
protected CallResult<T> Deserialize<T>(JToken obj, bool checkObject = true, JsonSerializer serializer = null)
|
protected CallResult<T> Deserialize<T>(JToken obj, bool checkObject = true, JsonSerializer serializer = null)
|
||||||
{
|
{
|
||||||
if (serializer == null)
|
if (serializer == null)
|
||||||
@ -218,6 +233,10 @@ namespace CryptoExchange.Net
|
|||||||
|| type == typeof(decimal);
|
|| type == typeof(decimal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generate a unique id
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
protected int NextId()
|
protected int NextId()
|
||||||
{
|
{
|
||||||
lock (idLock)
|
lock (idLock)
|
||||||
@ -227,18 +246,24 @@ namespace CryptoExchange.Net
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static string FillPathParameter(string endpoint, params string[] values)
|
/// <summary>
|
||||||
|
/// Fill parameters in a path. Parameters are specified by '{}' and should be specified in occuring sequence
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path">The total path string</param>
|
||||||
|
/// <param name="values">The values to fill</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
protected static string FillPathParameter(string path, params string[] values)
|
||||||
{
|
{
|
||||||
foreach (var value in values)
|
foreach (var value in values)
|
||||||
{
|
{
|
||||||
int index = endpoint.IndexOf("{}", StringComparison.Ordinal);
|
int index = path.IndexOf("{}", StringComparison.Ordinal);
|
||||||
if (index >= 0)
|
if (index >= 0)
|
||||||
{
|
{
|
||||||
endpoint = endpoint.Remove(index, 2);
|
path = path.Remove(index, 2);
|
||||||
endpoint = endpoint.Insert(index, value);
|
path = path.Insert(index, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return endpoint;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void Dispose()
|
public virtual void Dispose()
|
||||||
|
@ -31,6 +31,12 @@ namespace CryptoExchange.Net
|
|||||||
parameters.Add(key, value);
|
parameters.Add(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a query string of the specified parameters
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="parameters">The parameters to use</param>
|
||||||
|
/// <param name="urlEncodeValues">Whether or not the values should be url encoded</param>
|
||||||
|
/// <returns></returns>
|
||||||
public static string CreateParamString(this Dictionary<string, object> parameters, bool urlEncodeValues)
|
public static string CreateParamString(this Dictionary<string, object> parameters, bool urlEncodeValues)
|
||||||
{
|
{
|
||||||
var uriString = "";
|
var uriString = "";
|
||||||
@ -45,6 +51,11 @@ namespace CryptoExchange.Net
|
|||||||
return uriString;
|
return uriString;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the string the secure string is representing
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="source">The source secure string</param>
|
||||||
|
/// <returns></returns>
|
||||||
public static string GetString(this SecureString source)
|
public static string GetString(this SecureString source)
|
||||||
{
|
{
|
||||||
lock (source)
|
lock (source)
|
||||||
|
@ -2,7 +2,13 @@
|
|||||||
{
|
{
|
||||||
public abstract class Error
|
public abstract class Error
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The error code
|
||||||
|
/// </summary>
|
||||||
public int Code { get; set; }
|
public int Code { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// The message for the error that occured
|
||||||
|
/// </summary>
|
||||||
public string Message { get; set; }
|
public string Message { get; set; }
|
||||||
|
|
||||||
protected Error(int code, string message)
|
protected Error(int code, string message)
|
||||||
|
@ -21,6 +21,9 @@ namespace CryptoExchange.Net
|
|||||||
{
|
{
|
||||||
public abstract class RestClient: BaseClient
|
public abstract class RestClient: BaseClient
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The factory for creating requests. Used for unit testing
|
||||||
|
/// </summary>
|
||||||
public IRequestFactory RequestFactory { get; set; } = new RequestFactory();
|
public IRequestFactory RequestFactory { get; set; } = new RequestFactory();
|
||||||
|
|
||||||
protected RateLimitingBehaviour rateLimitBehaviour;
|
protected RateLimitingBehaviour rateLimitBehaviour;
|
||||||
@ -30,11 +33,6 @@ namespace CryptoExchange.Net
|
|||||||
|
|
||||||
private List<IRateLimiter> rateLimiters;
|
private List<IRateLimiter> rateLimiters;
|
||||||
|
|
||||||
private static readonly JsonSerializer defaultSerializer = JsonSerializer.Create(new JsonSerializerSettings()
|
|
||||||
{
|
|
||||||
DateTimeZoneHandling = DateTimeZoneHandling.Utc
|
|
||||||
});
|
|
||||||
|
|
||||||
protected RestClient(ClientOptions exchangeOptions, AuthenticationProvider authenticationProvider): base(exchangeOptions, authenticationProvider)
|
protected RestClient(ClientOptions exchangeOptions, AuthenticationProvider authenticationProvider): base(exchangeOptions, authenticationProvider)
|
||||||
{
|
{
|
||||||
Configure(exchangeOptions);
|
Configure(exchangeOptions);
|
||||||
@ -103,6 +101,16 @@ namespace CryptoExchange.Net
|
|||||||
return new CallResult<long>(0, new CantConnectError() { Message = "Ping failed: " + reply.Status });
|
return new CallResult<long>(0, new CantConnectError() { Message = "Ping failed: " + reply.Status });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Execute a request
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">The expected result type</typeparam>
|
||||||
|
/// <param name="uri">The uri to send the request to</param>
|
||||||
|
/// <param name="method">The method of the request</param>
|
||||||
|
/// <param name="parameters">The parameters of the request</param>
|
||||||
|
/// <param name="signed">Whether or not the request should be authenticated</param>
|
||||||
|
/// <param name="checkResult">Whether or not the resulting object should be checked for missing properties in the mapping (only outputs if log verbosity is Debug)</param>
|
||||||
|
/// <returns></returns>
|
||||||
protected virtual async Task<CallResult<T>> ExecuteRequest<T>(Uri uri, string method = Constants.GetMethod, Dictionary<string, object> parameters = null, bool signed = false, bool checkResult = true) where T : class
|
protected virtual async Task<CallResult<T>> ExecuteRequest<T>(Uri uri, string method = Constants.GetMethod, Dictionary<string, object> parameters = null, bool signed = false, bool checkResult = true) where T : class
|
||||||
{
|
{
|
||||||
log.Write(LogVerbosity.Debug, $"Creating request for " + uri);
|
log.Write(LogVerbosity.Debug, $"Creating request for " + uri);
|
||||||
@ -149,6 +157,14 @@ namespace CryptoExchange.Net
|
|||||||
return result.Error != null ? new CallResult<T>(null, result.Error) : Deserialize<T>(result.Data, checkResult);
|
return result.Error != null ? new CallResult<T>(null, result.Error) : Deserialize<T>(result.Data, checkResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a request object
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uri">The uri to send the request to</param>
|
||||||
|
/// <param name="method">The method of the request</param>
|
||||||
|
/// <param name="parameters">The parameters of the request</param>
|
||||||
|
/// <param name="signed">Whether or not the request should be authenticated</param>
|
||||||
|
/// <returns></returns>
|
||||||
protected virtual IRequest ConstructRequest(Uri uri, string method, Dictionary<string, object> parameters, bool signed)
|
protected virtual IRequest ConstructRequest(Uri uri, string method, Dictionary<string, object> parameters, bool signed)
|
||||||
{
|
{
|
||||||
if (parameters == null)
|
if (parameters == null)
|
||||||
@ -184,6 +200,11 @@ namespace CryptoExchange.Net
|
|||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes the string data of the paramters to the request body stream
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request"></param>
|
||||||
|
/// <param name="stringData"></param>
|
||||||
protected virtual void WriteParamBody(IRequest request, string stringData)
|
protected virtual void WriteParamBody(IRequest request, string stringData)
|
||||||
{
|
{
|
||||||
var data = Encoding.UTF8.GetBytes(stringData);
|
var data = Encoding.UTF8.GetBytes(stringData);
|
||||||
@ -193,6 +214,11 @@ namespace CryptoExchange.Net
|
|||||||
stream.Write(data, 0, data.Length);
|
stream.Write(data, 0, data.Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes the parameters of the request to the request object, either in the query string or the request body
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request"></param>
|
||||||
|
/// <param name="parameters"></param>
|
||||||
protected virtual void WriteParamBody(IRequest request, Dictionary<string, object> parameters)
|
protected virtual void WriteParamBody(IRequest request, Dictionary<string, object> parameters)
|
||||||
{
|
{
|
||||||
if (requestBodyFormat == RequestBodyFormat.Json)
|
if (requestBodyFormat == RequestBodyFormat.Json)
|
||||||
@ -210,6 +236,11 @@ namespace CryptoExchange.Net
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Executes the request and returns the string result
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request">The request object to execute</param>
|
||||||
|
/// <returns></returns>
|
||||||
private async Task<CallResult<string>> ExecuteRequest(IRequest request)
|
private async Task<CallResult<string>> ExecuteRequest(IRequest request)
|
||||||
{
|
{
|
||||||
var returnedData = "";
|
var returnedData = "";
|
||||||
@ -258,6 +289,11 @@ namespace CryptoExchange.Net
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Parse an error response from the server. Only used when server returns a status other than Success(200)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="error">The string the request returned</param>
|
||||||
|
/// <returns></returns>
|
||||||
protected virtual Error ParseErrorResponse(string error)
|
protected virtual Error ParseErrorResponse(string error)
|
||||||
{
|
{
|
||||||
return new ServerError(error);
|
return new ServerError(error);
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Security.Authentication;
|
using System.Security.Authentication;
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using CryptoExchange.Net.Authentication;
|
using CryptoExchange.Net.Authentication;
|
||||||
@ -18,6 +17,9 @@ namespace CryptoExchange.Net
|
|||||||
public abstract class SocketClient: BaseClient
|
public abstract class SocketClient: BaseClient
|
||||||
{
|
{
|
||||||
#region fields
|
#region fields
|
||||||
|
/// <summary>
|
||||||
|
/// The factory for creating sockets. Used for unit testing
|
||||||
|
/// </summary>
|
||||||
public IWebsocketFactory SocketFactory { get; set; } = new WebsocketFactory();
|
public IWebsocketFactory SocketFactory { get; set; } = new WebsocketFactory();
|
||||||
|
|
||||||
private const SslProtocols protocols = SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls;
|
private const SslProtocols protocols = SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls;
|
||||||
@ -51,6 +53,11 @@ namespace CryptoExchange.Net
|
|||||||
dataInterpreter = handler;
|
dataInterpreter = handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a socket for an address
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="address">The address the socket should connect to</param>
|
||||||
|
/// <returns></returns>
|
||||||
protected virtual IWebsocket CreateSocket(string address)
|
protected virtual IWebsocket CreateSocket(string address)
|
||||||
{
|
{
|
||||||
var socket = SocketFactory.CreateWebsocket(log, address);
|
var socket = SocketFactory.CreateWebsocket(log, address);
|
||||||
@ -80,8 +87,20 @@ namespace CryptoExchange.Net
|
|||||||
protected virtual void SocketOpened(IWebsocket socket) { }
|
protected virtual void SocketOpened(IWebsocket socket) { }
|
||||||
protected virtual void SocketClosed(IWebsocket socket) { }
|
protected virtual void SocketClosed(IWebsocket socket) { }
|
||||||
protected virtual void SocketError(IWebsocket socket, Exception ex) { }
|
protected virtual void SocketError(IWebsocket socket, Exception ex) { }
|
||||||
protected abstract bool SocketReconnect(SocketSubscription socket, TimeSpan disconnectedTime);
|
/// <summary>
|
||||||
|
/// Handler for when a socket reconnects. Should return true if reconnection handling was successful or false if not ( will try to reconnect again ). The handler should
|
||||||
|
/// handle functionality like resubscribing and re-authenticating the socket.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="subscription">The socket subscription that was reconnected</param>
|
||||||
|
/// <param name="disconnectedTime">The time the socket was disconnected</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
protected abstract bool SocketReconnect(SocketSubscription subscription, TimeSpan disconnectedTime);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Connect a socket
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="socketSubscription">The subscription to connect</param>
|
||||||
|
/// <returns></returns>
|
||||||
protected virtual async Task<CallResult<bool>> ConnectSocket(SocketSubscription socketSubscription)
|
protected virtual async Task<CallResult<bool>> ConnectSocket(SocketSubscription socketSubscription)
|
||||||
{
|
{
|
||||||
socketSubscription.Socket.OnMessage += data => ProcessMessage(socketSubscription, data);
|
socketSubscription.Socket.OnMessage += data => ProcessMessage(socketSubscription, data);
|
||||||
@ -97,13 +116,22 @@ namespace CryptoExchange.Net
|
|||||||
return new CallResult<bool>(false, new CantConnectError());
|
return new CallResult<bool>(false, new CantConnectError());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void ProcessMessage(SocketSubscription sub, string data)
|
/// <summary>
|
||||||
|
/// The message handler. Normally distributes the received data to all data handlers
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="subscription">The subscription that received the data</param>
|
||||||
|
/// <param name="data">The data received</param>
|
||||||
|
protected virtual void ProcessMessage(SocketSubscription subscription, string data)
|
||||||
{
|
{
|
||||||
log.Write(LogVerbosity.Debug, $"Socket {sub.Socket.Id} received data: " + data);
|
log.Write(LogVerbosity.Debug, $"Socket {subscription.Socket.Id} received data: " + data);
|
||||||
foreach (var handler in sub.DataHandlers)
|
foreach (var handler in subscription.DataHandlers)
|
||||||
handler(sub, JToken.Parse(data));
|
handler(subscription, JToken.Parse(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handler for a socket closing. Reconnects the socket if needed, or removes it from the active socket list if not
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="socket">The socket that was closed</param>
|
||||||
protected virtual void SocketOnClose(IWebsocket socket)
|
protected virtual void SocketOnClose(IWebsocket socket)
|
||||||
{
|
{
|
||||||
if (socket.ShouldReconnect)
|
if (socket.ShouldReconnect)
|
||||||
@ -148,22 +176,43 @@ namespace CryptoExchange.Net
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Send data to the websocket
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">The type of the object to send</typeparam>
|
||||||
|
/// <param name="socket">The socket to send to</param>
|
||||||
|
/// <param name="obj">The object to send</param>
|
||||||
|
/// <param name="nullValueHandling">How null values should be serialized</param>
|
||||||
protected virtual void Send<T>(IWebsocket socket, T obj, NullValueHandling nullValueHandling = NullValueHandling.Ignore)
|
protected virtual void Send<T>(IWebsocket socket, T obj, NullValueHandling nullValueHandling = NullValueHandling.Ignore)
|
||||||
{
|
{
|
||||||
Send(socket, JsonConvert.SerializeObject(obj, Formatting.None, new JsonSerializerSettings { NullValueHandling = nullValueHandling }));
|
Send(socket, JsonConvert.SerializeObject(obj, Formatting.None, new JsonSerializerSettings { NullValueHandling = nullValueHandling }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Send string data to the websocket
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="socket">The socket to send to</param>
|
||||||
|
/// <param name="data">The data to send</param>
|
||||||
protected virtual void Send(IWebsocket socket, string data)
|
protected virtual void Send(IWebsocket socket, string data)
|
||||||
{
|
{
|
||||||
log.Write(LogVerbosity.Debug, $"Socket {socket.Id} sending data: {data}");
|
log.Write(LogVerbosity.Debug, $"Socket {socket.Id} sending data: {data}");
|
||||||
socket.Send(data);
|
socket.Send(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual async Task Unsubscribe(UpdateSubscription sub)
|
/// <summary>
|
||||||
|
/// Unsubscribe from a stream
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="subscription">The subscription to unsubscribe</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public virtual async Task Unsubscribe(UpdateSubscription subscription)
|
||||||
{
|
{
|
||||||
await sub.Close();
|
await subscription.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unsubscribe all subscriptions
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
public virtual async Task UnsubscribeAll()
|
public virtual async Task UnsubscribeAll()
|
||||||
{
|
{
|
||||||
await Task.Run(() =>
|
await Task.Run(() =>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user