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.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace CryptoExchange.Net
|
||||
{
|
||||
@ -21,13 +20,14 @@ namespace CryptoExchange.Net
|
||||
|
||||
protected static int lastId;
|
||||
protected static object idLock = new object();
|
||||
public static int LastId { get => lastId; }
|
||||
|
||||
private static readonly JsonSerializer defaultSerializer = JsonSerializer.Create(new JsonSerializerSettings()
|
||||
{
|
||||
DateTimeZoneHandling = DateTimeZoneHandling.Utc
|
||||
});
|
||||
|
||||
public static int LastId { get => lastId; }
|
||||
|
||||
public BaseClient(ExchangeOptions options, AuthenticationProvider authenticationProvider)
|
||||
{
|
||||
log = new Log();
|
||||
@ -60,12 +60,27 @@ namespace CryptoExchange.Net
|
||||
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)
|
||||
{
|
||||
var obj = JToken.Parse(data);
|
||||
return Deserialize<T>(obj, checkObject, serializer);
|
||||
return Deserialize<T>(JToken.Parse(data), 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)
|
||||
{
|
||||
if (serializer == null)
|
||||
@ -218,6 +233,10 @@ namespace CryptoExchange.Net
|
||||
|| type == typeof(decimal);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate a unique id
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected int NextId()
|
||||
{
|
||||
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)
|
||||
{
|
||||
int index = endpoint.IndexOf("{}", StringComparison.Ordinal);
|
||||
int index = path.IndexOf("{}", StringComparison.Ordinal);
|
||||
if (index >= 0)
|
||||
{
|
||||
endpoint = endpoint.Remove(index, 2);
|
||||
endpoint = endpoint.Insert(index, value);
|
||||
path = path.Remove(index, 2);
|
||||
path = path.Insert(index, value);
|
||||
}
|
||||
}
|
||||
return endpoint;
|
||||
return path;
|
||||
}
|
||||
|
||||
public virtual void Dispose()
|
||||
|
@ -31,6 +31,12 @@ namespace CryptoExchange.Net
|
||||
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)
|
||||
{
|
||||
var uriString = "";
|
||||
@ -45,6 +51,11 @@ namespace CryptoExchange.Net
|
||||
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)
|
||||
{
|
||||
lock (source)
|
||||
|
@ -2,7 +2,13 @@
|
||||
{
|
||||
public abstract class Error
|
||||
{
|
||||
/// <summary>
|
||||
/// The error code
|
||||
/// </summary>
|
||||
public int Code { get; set; }
|
||||
/// <summary>
|
||||
/// The message for the error that occured
|
||||
/// </summary>
|
||||
public string Message { get; set; }
|
||||
|
||||
protected Error(int code, string message)
|
||||
|
@ -21,6 +21,9 @@ namespace CryptoExchange.Net
|
||||
{
|
||||
public abstract class RestClient: BaseClient
|
||||
{
|
||||
/// <summary>
|
||||
/// The factory for creating requests. Used for unit testing
|
||||
/// </summary>
|
||||
public IRequestFactory RequestFactory { get; set; } = new RequestFactory();
|
||||
|
||||
protected RateLimitingBehaviour rateLimitBehaviour;
|
||||
@ -30,11 +33,6 @@ namespace CryptoExchange.Net
|
||||
|
||||
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)
|
||||
{
|
||||
Configure(exchangeOptions);
|
||||
@ -103,6 +101,16 @@ namespace CryptoExchange.Net
|
||||
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
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
/// <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)
|
||||
{
|
||||
if (parameters == null)
|
||||
@ -184,6 +200,11 @@ namespace CryptoExchange.Net
|
||||
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)
|
||||
{
|
||||
var data = Encoding.UTF8.GetBytes(stringData);
|
||||
@ -193,6 +214,11 @@ namespace CryptoExchange.Net
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
return new ServerError(error);
|
||||
|
@ -2,7 +2,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Authentication;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using CryptoExchange.Net.Authentication;
|
||||
@ -18,6 +17,9 @@ namespace CryptoExchange.Net
|
||||
public abstract class SocketClient: BaseClient
|
||||
{
|
||||
#region fields
|
||||
/// <summary>
|
||||
/// The factory for creating sockets. Used for unit testing
|
||||
/// </summary>
|
||||
public IWebsocketFactory SocketFactory { get; set; } = new WebsocketFactory();
|
||||
|
||||
private const SslProtocols protocols = SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls;
|
||||
@ -51,6 +53,11 @@ namespace CryptoExchange.Net
|
||||
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)
|
||||
{
|
||||
var socket = SocketFactory.CreateWebsocket(log, address);
|
||||
@ -80,8 +87,20 @@ namespace CryptoExchange.Net
|
||||
protected virtual void SocketOpened(IWebsocket socket) { }
|
||||
protected virtual void SocketClosed(IWebsocket socket) { }
|
||||
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)
|
||||
{
|
||||
socketSubscription.Socket.OnMessage += data => ProcessMessage(socketSubscription, data);
|
||||
@ -97,13 +116,22 @@ namespace CryptoExchange.Net
|
||||
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);
|
||||
foreach (var handler in sub.DataHandlers)
|
||||
handler(sub, JToken.Parse(data));
|
||||
log.Write(LogVerbosity.Debug, $"Socket {subscription.Socket.Id} received data: " + data);
|
||||
foreach (var handler in subscription.DataHandlers)
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
log.Write(LogVerbosity.Debug, $"Socket {socket.Id} sending data: {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()
|
||||
{
|
||||
await Task.Run(() =>
|
||||
|
Loading…
x
Reference in New Issue
Block a user