1
0
mirror of https://github.com/JKorf/CryptoExchange.Net synced 2025-06-07 16:06:15 +00:00

Various fixes

This commit is contained in:
JKorf 2018-03-05 09:38:24 +01:00
parent 30301ab8d7
commit edcf91ca7c
6 changed files with 82 additions and 34 deletions

View File

@ -4,15 +4,16 @@ namespace CryptoExchange.Net.Authentication
{ {
public abstract class AuthenticationProvider public abstract class AuthenticationProvider
{ {
protected ApiCredentials credentials; public ApiCredentials Credentials { get; }
protected AuthenticationProvider(ApiCredentials credentials) protected AuthenticationProvider(ApiCredentials credentials)
{ {
this.credentials = credentials; Credentials = credentials;
} }
public abstract string AddAuthenticationToUriString(string uri, bool signed); public abstract string AddAuthenticationToUriString(string uri, bool signed);
public abstract IRequest AddAuthenticationToRequest(IRequest request, bool signed); public abstract IRequest AddAuthenticationToRequest(IRequest request, bool signed);
public abstract string Sign(string toSign);
protected string ByteToString(byte[] buff) protected string ByteToString(byte[] buff)
{ {

View File

@ -7,7 +7,7 @@
<PropertyGroup> <PropertyGroup>
<PackageId>CryptoExchange.Net</PackageId> <PackageId>CryptoExchange.Net</PackageId>
<Authors>JKorf</Authors> <Authors>JKorf</Authors>
<PackageVersion>0.0.2</PackageVersion> <PackageVersion>0.0.4</PackageVersion>
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance> <PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
<PackageProjectUrl>https://github.com/JKorf/CryptoExchange.Net</PackageProjectUrl> <PackageProjectUrl>https://github.com/JKorf/CryptoExchange.Net</PackageProjectUrl>
<PackageLicenseUrl>https://github.com/JKorf/CryptoExchange.Net/blob/master/LICENSE</PackageLicenseUrl> <PackageLicenseUrl>https://github.com/JKorf/CryptoExchange.Net/blob/master/LICENSE</PackageLicenseUrl>

View File

@ -30,6 +30,10 @@
public class ServerError: Error public class ServerError: Error
{ {
public ServerError(string message) : base(3, "Server error: " + message) { } public ServerError(string message) : base(3, "Server error: " + message) { }
public ServerError(int code, string message) : base(code, message)
{
}
} }
public class WebError : Error public class WebError : Error

View File

@ -22,13 +22,13 @@ namespace CryptoExchange.Net
protected Log log; protected Log log;
protected ApiProxy apiProxy; protected ApiProxy apiProxy;
private AuthenticationProvider authProvider; protected AuthenticationProvider authProvider;
private List<IRateLimiter> rateLimiters; private List<IRateLimiter> rateLimiters;
protected ExchangeClient(ExchangeOptions exchangeOptions, AuthenticationProvider authentictationProvider) protected ExchangeClient(ExchangeOptions exchangeOptions, AuthenticationProvider authenticationProvider)
{ {
log = new Log(); log = new Log();
authProvider = authentictationProvider; authProvider = authenticationProvider;
Configure(exchangeOptions); Configure(exchangeOptions);
} }
@ -80,6 +80,25 @@ namespace CryptoExchange.Net
if(signed && authProvider == null) if(signed && authProvider == null)
return new CallResult<T>(null, new NoApiCredentialsError()); return new CallResult<T>(null, new NoApiCredentialsError());
var request = ConstructRequest(uri, method, parameters, signed);
if (apiProxy != null)
request.SetProxy(apiProxy.Host, apiProxy.Port);
foreach (var limiter in rateLimiters)
{
var limitedBy = limiter.LimitRequest(uri.AbsolutePath);
if (limitedBy > 0)
log.Write(LogVerbosity.Debug, $"Request {uri.AbsolutePath} was limited by {limitedBy}ms by {limiter.GetType().Name}");
}
log.Write(LogVerbosity.Debug, $"Sending request to {request.Uri}");
var result = await ExecuteRequest(request).ConfigureAwait(false);
return result.Error != null ? new CallResult<T>(null, result.Error) : Deserialize<T>(result.Data);
}
protected virtual IRequest ConstructRequest(Uri uri, string method, Dictionary<string, object> parameters, bool signed)
{
var uriString = uri.ToString(); var uriString = uri.ToString();
if (parameters != null) if (parameters != null)
@ -90,28 +109,16 @@ namespace CryptoExchange.Net
uriString += $"{string.Join("&", parameters.Select(s => $"{s.Key}={s.Value}"))}"; uriString += $"{string.Join("&", parameters.Select(s => $"{s.Key}={s.Value}"))}";
} }
if(authProvider != null) if (authProvider != null)
uriString = authProvider.AddAuthenticationToUriString(uriString, signed); uriString = authProvider.AddAuthenticationToUriString(uriString, signed);
var request = RequestFactory.Create(uriString); var request = RequestFactory.Create(uriString);
request.Method = method; request.Method = method;
if (apiProxy != null) if (authProvider != null)
request.SetProxy(apiProxy.Host, apiProxy.Port);
if(authProvider != null)
request = authProvider.AddAuthenticationToRequest(request, signed); request = authProvider.AddAuthenticationToRequest(request, signed);
foreach (var limiter in rateLimiters) return request;
{
var limitedBy = limiter.LimitRequest(uri.AbsolutePath);
if (limitedBy > 0)
log.Write(LogVerbosity.Debug, $"Request {uri.AbsolutePath} was limited by {limitedBy}ms by {limiter.GetType().Name}");
}
log.Write(LogVerbosity.Debug, $"Sending request to {uriString}");
var result = await ExecuteRequest(request);
return result.Error != null ? new CallResult<T>(null, result.Error) : Deserialize<T>(result.Data);
} }
private async Task<CallResult<string>> ExecuteRequest(IRequest request) private async Task<CallResult<string>> ExecuteRequest(IRequest request)
@ -119,7 +126,7 @@ namespace CryptoExchange.Net
var returnedData = ""; var returnedData = "";
try try
{ {
var response = request.GetResponse(); var response = await request.GetResponse().ConfigureAwait(false);
using (var reader = new StreamReader(response.GetResponseStream())) using (var reader = new StreamReader(response.GetResponseStream()))
{ {
returnedData = await reader.ReadToEndAsync().ConfigureAwait(false); returnedData = await reader.ReadToEndAsync().ConfigureAwait(false);
@ -129,11 +136,11 @@ namespace CryptoExchange.Net
catch (WebException we) catch (WebException we)
{ {
var response = (HttpWebResponse)we.Response; var response = (HttpWebResponse)we.Response;
string responseData = null;
try try
{ {
var reader = new StreamReader(response.GetResponseStream()); var reader = new StreamReader(response.GetResponseStream());
responseData = reader.ReadToEnd(); var responseData = await reader.ReadToEndAsync().ConfigureAwait(false);
return new CallResult<string>(null, ParseErrorResponse(responseData));
} }
catch (Exception) catch (Exception)
{ {
@ -143,9 +150,6 @@ namespace CryptoExchange.Net
if (response == null) if (response == null)
return new CallResult<string>(null, new WebError(infoMessage)); return new CallResult<string>(null, new WebError(infoMessage));
if (responseData != null)
infoMessage = "Server returned error: " + responseData;
else
infoMessage = $"Status: {response.StatusCode}-{response.StatusDescription}, Message: {we.Message}"; infoMessage = $"Status: {response.StatusCode}-{response.StatusDescription}, Message: {we.Message}";
return new CallResult<string>(null, new ServerError(infoMessage)); return new CallResult<string>(null, new ServerError(infoMessage));
} }
@ -155,6 +159,11 @@ namespace CryptoExchange.Net
} }
} }
protected virtual Error ParseErrorResponse(string error)
{
return new ServerError(error);
}
private CallResult<T> Deserialize<T>(string data) where T: class private CallResult<T> Deserialize<T>(string data) where T: class
{ {
try try

View File

@ -1,5 +1,7 @@
using System; using System;
using System.IO;
using System.Net; using System.Net;
using System.Threading.Tasks;
namespace CryptoExchange.Net.Interfaces namespace CryptoExchange.Net.Interfaces
{ {
@ -10,6 +12,12 @@ namespace CryptoExchange.Net.Interfaces
string Method { get; set; } string Method { get; set; }
void SetProxy(string host, int port); void SetProxy(string host, int port);
IResponse GetResponse();
string ContentType { get; set; }
string Accept { get; set; }
long ContentLength { get; set; }
Task<Stream> GetRequestStream();
Task<IResponse> GetResponse();
} }
} }

View File

@ -1,5 +1,7 @@
using System; using System;
using System.IO;
using System.Net; using System.Net;
using System.Threading.Tasks;
using CryptoExchange.Net.Interfaces; using CryptoExchange.Net.Interfaces;
namespace CryptoExchange.Net.Requests namespace CryptoExchange.Net.Requests
@ -18,11 +20,30 @@ namespace CryptoExchange.Net.Requests
get => request.Headers; get => request.Headers;
set => request.Headers = value; set => request.Headers = value;
} }
public string ContentType
{
get => request.ContentType;
set => request.ContentType = value;
}
public string Accept
{
get => ((HttpWebRequest)request).Accept;
set => ((HttpWebRequest)request).Accept = value;
}
public long ContentLength
{
get => ((HttpWebRequest)request).ContentLength;
set => ((HttpWebRequest)request).ContentLength = value;
}
public string Method public string Method
{ {
get => request.Method; get => request.Method;
set => request.Method = value; set => request.Method = value;
} }
public Uri Uri => request.RequestUri; public Uri Uri => request.RequestUri;
public void SetProxy(string host, int port) public void SetProxy(string host, int port)
@ -30,9 +51,14 @@ namespace CryptoExchange.Net.Requests
request.Proxy = new WebProxy(host, port); request.Proxy = new WebProxy(host, port);
} }
public IResponse GetResponse() public async Task<Stream> GetRequestStream()
{ {
return new Response(request.GetResponse()); return await request.GetRequestStreamAsync();
}
public async Task<IResponse> GetResponse()
{
return new Response(await request.GetResponseAsync().ConfigureAwait(false));
} }
} }
} }