mirror of
https://github.com/JKorf/CryptoExchange.Net
synced 2025-06-08 08:26:20 +00:00
Added Request info and ResponseTime to WebCallResult, refactored CallResult ctors
This commit is contained in:
parent
c6bf0d67a4
commit
8f6e853e13
@ -93,28 +93,28 @@ namespace CryptoExchange.Net
|
|||||||
{
|
{
|
||||||
var info = "Empty data object received";
|
var info = "Empty data object received";
|
||||||
log.Write(LogLevel.Error, info);
|
log.Write(LogLevel.Error, info);
|
||||||
return new CallResult<JToken>(null, new DeserializeError(info, data));
|
return new CallResult<JToken>(new DeserializeError(info, data));
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return new CallResult<JToken>(JToken.Parse(data), null);
|
return new CallResult<JToken>(JToken.Parse(data));
|
||||||
}
|
}
|
||||||
catch (JsonReaderException jre)
|
catch (JsonReaderException jre)
|
||||||
{
|
{
|
||||||
var info = $"Deserialize JsonReaderException: {jre.Message}, Path: {jre.Path}, LineNumber: {jre.LineNumber}, LinePosition: {jre.LinePosition}";
|
var info = $"Deserialize JsonReaderException: {jre.Message}, Path: {jre.Path}, LineNumber: {jre.LineNumber}, LinePosition: {jre.LinePosition}";
|
||||||
return new CallResult<JToken>(null, new DeserializeError(info, data));
|
return new CallResult<JToken>(new DeserializeError(info, data));
|
||||||
}
|
}
|
||||||
catch (JsonSerializationException jse)
|
catch (JsonSerializationException jse)
|
||||||
{
|
{
|
||||||
var info = $"Deserialize JsonSerializationException: {jse.Message}";
|
var info = $"Deserialize JsonSerializationException: {jse.Message}";
|
||||||
return new CallResult<JToken>(null, new DeserializeError(info, data));
|
return new CallResult<JToken>(new DeserializeError(info, data));
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
var exceptionInfo = ex.ToLogString();
|
var exceptionInfo = ex.ToLogString();
|
||||||
var info = $"Deserialize Unknown Exception: {exceptionInfo}";
|
var info = $"Deserialize Unknown Exception: {exceptionInfo}";
|
||||||
return new CallResult<JToken>(null, new DeserializeError(info, data));
|
return new CallResult<JToken>(new DeserializeError(info, data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,7 +132,7 @@ namespace CryptoExchange.Net
|
|||||||
if (!tokenResult)
|
if (!tokenResult)
|
||||||
{
|
{
|
||||||
log.Write(LogLevel.Error, tokenResult.Error!.Message);
|
log.Write(LogLevel.Error, tokenResult.Error!.Message);
|
||||||
return new CallResult<T>(default, tokenResult.Error);
|
return new CallResult<T>( tokenResult.Error);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Deserialize<T>(tokenResult.Data, serializer, requestId);
|
return Deserialize<T>(tokenResult.Data, serializer, requestId);
|
||||||
@ -152,26 +152,26 @@ namespace CryptoExchange.Net
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return new CallResult<T>(obj.ToObject<T>(serializer), null);
|
return new CallResult<T>(obj.ToObject<T>(serializer)!);
|
||||||
}
|
}
|
||||||
catch (JsonReaderException jre)
|
catch (JsonReaderException jre)
|
||||||
{
|
{
|
||||||
var info = $"{(requestId != null ? $"[{requestId}] " : "")}Deserialize JsonReaderException: {jre.Message} Path: {jre.Path}, LineNumber: {jre.LineNumber}, LinePosition: {jre.LinePosition}, data: {obj}";
|
var info = $"{(requestId != null ? $"[{requestId}] " : "")}Deserialize JsonReaderException: {jre.Message} Path: {jre.Path}, LineNumber: {jre.LineNumber}, LinePosition: {jre.LinePosition}, data: {obj}";
|
||||||
log.Write(LogLevel.Error, info);
|
log.Write(LogLevel.Error, info);
|
||||||
return new CallResult<T>(default, new DeserializeError(info, obj));
|
return new CallResult<T>(new DeserializeError(info, obj));
|
||||||
}
|
}
|
||||||
catch (JsonSerializationException jse)
|
catch (JsonSerializationException jse)
|
||||||
{
|
{
|
||||||
var info = $"{(requestId != null ? $"[{requestId}] " : "")}Deserialize JsonSerializationException: {jse.Message} data: {obj}";
|
var info = $"{(requestId != null ? $"[{requestId}] " : "")}Deserialize JsonSerializationException: {jse.Message} data: {obj}";
|
||||||
log.Write(LogLevel.Error, info);
|
log.Write(LogLevel.Error, info);
|
||||||
return new CallResult<T>(default, new DeserializeError(info, obj));
|
return new CallResult<T>(new DeserializeError(info, obj));
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
var exceptionInfo = ex.ToLogString();
|
var exceptionInfo = ex.ToLogString();
|
||||||
var info = $"{(requestId != null ? $"[{requestId}] " : "")}Deserialize Unknown Exception: {exceptionInfo}, data: {obj}";
|
var info = $"{(requestId != null ? $"[{requestId}] " : "")}Deserialize Unknown Exception: {exceptionInfo}, data: {obj}";
|
||||||
log.Write(LogLevel.Error, info);
|
log.Write(LogLevel.Error, info);
|
||||||
return new CallResult<T>(default, new DeserializeError(info, obj));
|
return new CallResult<T>(new DeserializeError(info, obj));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,7 +208,7 @@ namespace CryptoExchange.Net
|
|||||||
// If we don't have to keep track of the original json data we can use the JsonTextReader to deserialize the stream directly
|
// If we don't have to keep track of the original json data we can use the JsonTextReader to deserialize the stream directly
|
||||||
// into the desired object, which has increased performance over first reading the string value into memory and deserializing from that
|
// into the desired object, which has increased performance over first reading the string value into memory and deserializing from that
|
||||||
using var jsonReader = new JsonTextReader(reader);
|
using var jsonReader = new JsonTextReader(reader);
|
||||||
return new CallResult<T>(serializer.Deserialize<T>(jsonReader), null);
|
return new CallResult<T>(serializer.Deserialize<T>(jsonReader)!);
|
||||||
}
|
}
|
||||||
catch (JsonReaderException jre)
|
catch (JsonReaderException jre)
|
||||||
{
|
{
|
||||||
@ -222,7 +222,7 @@ namespace CryptoExchange.Net
|
|||||||
else
|
else
|
||||||
data = "[Data only available in Debug LogLevel]";
|
data = "[Data only available in Debug LogLevel]";
|
||||||
log.Write(LogLevel.Error, $"{(requestId != null ? $"[{requestId}] " : "")}Deserialize JsonReaderException: {jre.Message}, Path: {jre.Path}, LineNumber: {jre.LineNumber}, LinePosition: {jre.LinePosition}, data: {data}");
|
log.Write(LogLevel.Error, $"{(requestId != null ? $"[{requestId}] " : "")}Deserialize JsonReaderException: {jre.Message}, Path: {jre.Path}, LineNumber: {jre.LineNumber}, LinePosition: {jre.LinePosition}, data: {data}");
|
||||||
return new CallResult<T>(default, new DeserializeError($"Deserialize JsonReaderException: {jre.Message}, Path: {jre.Path}, LineNumber: {jre.LineNumber}, LinePosition: {jre.LinePosition}", data));
|
return new CallResult<T>(new DeserializeError($"Deserialize JsonReaderException: {jre.Message}, Path: {jre.Path}, LineNumber: {jre.LineNumber}, LinePosition: {jre.LinePosition}", data));
|
||||||
}
|
}
|
||||||
catch (JsonSerializationException jse)
|
catch (JsonSerializationException jse)
|
||||||
{
|
{
|
||||||
@ -236,7 +236,7 @@ namespace CryptoExchange.Net
|
|||||||
data = "[Data only available in Debug LogLevel]";
|
data = "[Data only available in Debug LogLevel]";
|
||||||
|
|
||||||
log.Write(LogLevel.Error, $"{(requestId != null ? $"[{requestId}] " : "")}Deserialize JsonSerializationException: {jse.Message}, data: {data}");
|
log.Write(LogLevel.Error, $"{(requestId != null ? $"[{requestId}] " : "")}Deserialize JsonSerializationException: {jse.Message}, data: {data}");
|
||||||
return new CallResult<T>(default, new DeserializeError($"Deserialize JsonSerializationException: {jse.Message}", data));
|
return new CallResult<T>(new DeserializeError($"Deserialize JsonSerializationException: {jse.Message}", data));
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@ -250,7 +250,7 @@ namespace CryptoExchange.Net
|
|||||||
|
|
||||||
var exceptionInfo = ex.ToLogString();
|
var exceptionInfo = ex.ToLogString();
|
||||||
log.Write(LogLevel.Error, $"{(requestId != null ? $"[{requestId}] " : "")}Deserialize Unknown Exception: {exceptionInfo}, data: {data}");
|
log.Write(LogLevel.Error, $"{(requestId != null ? $"[{requestId}] " : "")}Deserialize Unknown Exception: {exceptionInfo}, data: {data}");
|
||||||
return new CallResult<T>(default, new DeserializeError($"Deserialize Unknown Exception: {exceptionInfo}", data));
|
return new CallResult<T>(new DeserializeError($"Deserialize Unknown Exception: {exceptionInfo}", data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,7 +136,7 @@ namespace CryptoExchange.Net
|
|||||||
if (signed && apiClient.AuthenticationProvider == null)
|
if (signed && apiClient.AuthenticationProvider == null)
|
||||||
{
|
{
|
||||||
log.Write(LogLevel.Warning, $"[{requestId}] Request {uri.AbsolutePath} failed because no ApiCredentials were provided");
|
log.Write(LogLevel.Warning, $"[{requestId}] Request {uri.AbsolutePath} failed because no ApiCredentials were provided");
|
||||||
return new WebCallResult<T>(null, null, null, new NoApiCredentialsError());
|
return new WebCallResult<T>(new NoApiCredentialsError());
|
||||||
}
|
}
|
||||||
|
|
||||||
var paramsPosition = parameterPosition ?? ParameterPositions[method];
|
var paramsPosition = parameterPosition ?? ParameterPositions[method];
|
||||||
@ -145,7 +145,7 @@ namespace CryptoExchange.Net
|
|||||||
{
|
{
|
||||||
var limitResult = await limiter.LimitRequestAsync(log, uri.AbsolutePath, method, signed, apiClient.Options.ApiCredentials?.Key, apiClient.Options.RateLimitingBehaviour, requestWeight, cancellationToken).ConfigureAwait(false);
|
var limitResult = await limiter.LimitRequestAsync(log, uri.AbsolutePath, method, signed, apiClient.Options.ApiCredentials?.Key, apiClient.Options.RateLimitingBehaviour, requestWeight, cancellationToken).ConfigureAwait(false);
|
||||||
if (!limitResult.Success)
|
if (!limitResult.Success)
|
||||||
return new WebCallResult<T>(null, null, null, limitResult.Error);
|
return new WebCallResult<T>(limitResult.Error!);
|
||||||
}
|
}
|
||||||
|
|
||||||
string? paramString = "";
|
string? paramString = "";
|
||||||
@ -196,16 +196,16 @@ namespace CryptoExchange.Net
|
|||||||
// Validate if it is valid json. Sometimes other data will be returned, 502 error html pages for example
|
// Validate if it is valid json. Sometimes other data will be returned, 502 error html pages for example
|
||||||
var parseResult = ValidateJson(data);
|
var parseResult = ValidateJson(data);
|
||||||
if (!parseResult.Success)
|
if (!parseResult.Success)
|
||||||
return WebCallResult<T>.CreateErrorResult(response.StatusCode, response.ResponseHeaders, parseResult.Error!);
|
return new WebCallResult<T>(response.StatusCode, response.ResponseHeaders, ClientOptions.OutputOriginalData ? data : null, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), default, parseResult.Error!);
|
||||||
|
|
||||||
// Let the library implementation see if it is an error response, and if so parse the error
|
// Let the library implementation see if it is an error response, and if so parse the error
|
||||||
var error = await TryParseErrorAsync(parseResult.Data).ConfigureAwait(false);
|
var error = await TryParseErrorAsync(parseResult.Data).ConfigureAwait(false);
|
||||||
if (error != null)
|
if (error != null)
|
||||||
return WebCallResult<T>.CreateErrorResult(response.StatusCode, response.ResponseHeaders, error);
|
return new WebCallResult<T>(response.StatusCode, response.ResponseHeaders, ClientOptions.OutputOriginalData ? data : null, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), default, error!);
|
||||||
|
|
||||||
// Not an error, so continue deserializing
|
// Not an error, so continue deserializing
|
||||||
var deserializeResult = Deserialize<T>(parseResult.Data, deserializer, request.RequestId);
|
var deserializeResult = Deserialize<T>(parseResult.Data, deserializer, request.RequestId);
|
||||||
return new WebCallResult<T>(response.StatusCode, response.ResponseHeaders, ClientOptions.OutputOriginalData ? data: null, deserializeResult.Data, deserializeResult.Error);
|
return new WebCallResult<T>(response.StatusCode, response.ResponseHeaders, ClientOptions.OutputOriginalData ? data: null, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), deserializeResult.Data, deserializeResult.Error);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -214,7 +214,7 @@ namespace CryptoExchange.Net
|
|||||||
responseStream.Close();
|
responseStream.Close();
|
||||||
response.Close();
|
response.Close();
|
||||||
|
|
||||||
return new WebCallResult<T>(statusCode, headers, ClientOptions.OutputOriginalData ? desResult.OriginalData : null, desResult.Data, desResult.Error);
|
return new WebCallResult<T>(statusCode, headers, ClientOptions.OutputOriginalData ? desResult.OriginalData : null, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), desResult.Data, desResult.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -229,7 +229,7 @@ namespace CryptoExchange.Net
|
|||||||
var error = parseResult.Success ? ParseErrorResponse(parseResult.Data) : parseResult.Error!;
|
var error = parseResult.Success ? ParseErrorResponse(parseResult.Data) : parseResult.Error!;
|
||||||
if(error.Code == null || error.Code == 0)
|
if(error.Code == null || error.Code == 0)
|
||||||
error.Code = (int)response.StatusCode;
|
error.Code = (int)response.StatusCode;
|
||||||
return new WebCallResult<T>(statusCode, headers, default, error);
|
return new WebCallResult<T>(statusCode, headers, data, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), default, error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (HttpRequestException requestException)
|
catch (HttpRequestException requestException)
|
||||||
@ -237,7 +237,7 @@ namespace CryptoExchange.Net
|
|||||||
// Request exception, can't reach server for instance
|
// Request exception, can't reach server for instance
|
||||||
var exceptionInfo = requestException.ToLogString();
|
var exceptionInfo = requestException.ToLogString();
|
||||||
log.Write(LogLevel.Warning, $"[{request.RequestId}] Request exception: " + exceptionInfo);
|
log.Write(LogLevel.Warning, $"[{request.RequestId}] Request exception: " + exceptionInfo);
|
||||||
return new WebCallResult<T>(null, null, default, new WebError(exceptionInfo));
|
return new WebCallResult<T>(null, null, null, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), default, new WebError(exceptionInfo));
|
||||||
}
|
}
|
||||||
catch (OperationCanceledException canceledException)
|
catch (OperationCanceledException canceledException)
|
||||||
{
|
{
|
||||||
@ -245,13 +245,13 @@ namespace CryptoExchange.Net
|
|||||||
{
|
{
|
||||||
// Cancellation token canceled by caller
|
// Cancellation token canceled by caller
|
||||||
log.Write(LogLevel.Warning, $"[{request.RequestId}] Request canceled by cancellation token");
|
log.Write(LogLevel.Warning, $"[{request.RequestId}] Request canceled by cancellation token");
|
||||||
return new WebCallResult<T>(null, null, default, new CancellationRequestedError());
|
return new WebCallResult<T>(null, null, null, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), default, new CancellationRequestedError());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Request timed out
|
// Request timed out
|
||||||
log.Write(LogLevel.Warning, $"[{request.RequestId}] Request timed out: " + canceledException.ToLogString());
|
log.Write(LogLevel.Warning, $"[{request.RequestId}] Request timed out: " + canceledException.ToLogString());
|
||||||
return new WebCallResult<T>(null, null, default, new WebError($"[{request.RequestId}] Request timed out"));
|
return new WebCallResult<T>(null, null, null, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), default, new WebError($"[{request.RequestId}] Request timed out"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -163,7 +163,7 @@ namespace CryptoExchange.Net
|
|||||||
}
|
}
|
||||||
catch (OperationCanceledException)
|
catch (OperationCanceledException)
|
||||||
{
|
{
|
||||||
return new CallResult<UpdateSubscription>(null, new CancellationRequestedError());
|
return new CallResult<UpdateSubscription>(new CancellationRequestedError());
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
@ -184,7 +184,7 @@ namespace CryptoExchange.Net
|
|||||||
|
|
||||||
var connectResult = await ConnectIfNeededAsync(socketConnection, authenticated).ConfigureAwait(false);
|
var connectResult = await ConnectIfNeededAsync(socketConnection, authenticated).ConfigureAwait(false);
|
||||||
if (!connectResult)
|
if (!connectResult)
|
||||||
return new CallResult<UpdateSubscription>(null, connectResult.Error);
|
return new CallResult<UpdateSubscription>(connectResult.Error!);
|
||||||
|
|
||||||
if (needsConnecting)
|
if (needsConnecting)
|
||||||
log.Write(LogLevel.Debug, $"Socket {socketConnection.Socket.Id} connected to {url} {(request == null ? "": "with request " + JsonConvert.SerializeObject(request))}");
|
log.Write(LogLevel.Debug, $"Socket {socketConnection.Socket.Id} connected to {url} {(request == null ? "": "with request " + JsonConvert.SerializeObject(request))}");
|
||||||
@ -198,7 +198,7 @@ namespace CryptoExchange.Net
|
|||||||
if (socketConnection.PausedActivity)
|
if (socketConnection.PausedActivity)
|
||||||
{
|
{
|
||||||
log.Write(LogLevel.Information, $"Socket {socketConnection.Socket.Id} has been paused, can't subscribe at this moment");
|
log.Write(LogLevel.Information, $"Socket {socketConnection.Socket.Id} has been paused, can't subscribe at this moment");
|
||||||
return new CallResult<UpdateSubscription>(default, new ServerError("Socket is paused"));
|
return new CallResult<UpdateSubscription>( new ServerError("Socket is paused"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request != null)
|
if (request != null)
|
||||||
@ -208,7 +208,7 @@ namespace CryptoExchange.Net
|
|||||||
if (!subResult)
|
if (!subResult)
|
||||||
{
|
{
|
||||||
await socketConnection.CloseAsync(subscription).ConfigureAwait(false);
|
await socketConnection.CloseAsync(subscription).ConfigureAwait(false);
|
||||||
return new CallResult<UpdateSubscription>(null, subResult.Error);
|
return new CallResult<UpdateSubscription>(subResult.Error!);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -226,7 +226,7 @@ namespace CryptoExchange.Net
|
|||||||
await socketConnection.CloseAsync(subscription).ConfigureAwait(false);
|
await socketConnection.CloseAsync(subscription).ConfigureAwait(false);
|
||||||
}, false);
|
}, false);
|
||||||
}
|
}
|
||||||
return new CallResult<UpdateSubscription>(new UpdateSubscription(socketConnection, subscription), null);
|
return new CallResult<UpdateSubscription>(new UpdateSubscription(socketConnection, subscription));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -242,9 +242,15 @@ namespace CryptoExchange.Net
|
|||||||
await socketConnection.SendAndWaitAsync(request, ClientOptions.SocketResponseTimeout, data => HandleSubscriptionResponse(socketConnection, subscription, request, data, out callResult)).ConfigureAwait(false);
|
await socketConnection.SendAndWaitAsync(request, ClientOptions.SocketResponseTimeout, data => HandleSubscriptionResponse(socketConnection, subscription, request, data, out callResult)).ConfigureAwait(false);
|
||||||
|
|
||||||
if (callResult?.Success == true)
|
if (callResult?.Success == true)
|
||||||
|
{
|
||||||
subscription.Confirmed = true;
|
subscription.Confirmed = true;
|
||||||
|
return new CallResult<bool>(true);
|
||||||
|
}
|
||||||
|
|
||||||
return new CallResult<bool>(callResult?.Success ?? false, callResult == null ? new ServerError("No response on subscription request received"): callResult.Error);
|
if(callResult== null)
|
||||||
|
return new CallResult<bool>(new ServerError("No response on subscription request received"));
|
||||||
|
|
||||||
|
return new CallResult<bool>(callResult.Error!);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -286,7 +292,7 @@ namespace CryptoExchange.Net
|
|||||||
|
|
||||||
var connectResult = await ConnectIfNeededAsync(socketConnection, authenticated).ConfigureAwait(false);
|
var connectResult = await ConnectIfNeededAsync(socketConnection, authenticated).ConfigureAwait(false);
|
||||||
if (!connectResult)
|
if (!connectResult)
|
||||||
return new CallResult<T>(default, connectResult.Error);
|
return new CallResult<T>(connectResult.Error!);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@ -299,7 +305,7 @@ namespace CryptoExchange.Net
|
|||||||
if (socketConnection.PausedActivity)
|
if (socketConnection.PausedActivity)
|
||||||
{
|
{
|
||||||
log.Write(LogLevel.Information, $"Socket {socketConnection.Socket.Id} has been paused, can't send query at this moment");
|
log.Write(LogLevel.Information, $"Socket {socketConnection.Socket.Id} has been paused, can't send query at this moment");
|
||||||
return new CallResult<T>(default, new ServerError("Socket is paused"));
|
return new CallResult<T>(new ServerError("Socket is paused"));
|
||||||
}
|
}
|
||||||
|
|
||||||
return await QueryAndWaitAsync<T>(socketConnection, request).ConfigureAwait(false);
|
return await QueryAndWaitAsync<T>(socketConnection, request).ConfigureAwait(false);
|
||||||
@ -314,7 +320,7 @@ namespace CryptoExchange.Net
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
protected virtual async Task<CallResult<T>> QueryAndWaitAsync<T>(SocketConnection socket, object request)
|
protected virtual async Task<CallResult<T>> QueryAndWaitAsync<T>(SocketConnection socket, object request)
|
||||||
{
|
{
|
||||||
var dataResult = new CallResult<T>(default, new ServerError("No response on query received"));
|
var dataResult = new CallResult<T>(new ServerError("No response on query received"));
|
||||||
await socket.SendAndWaitAsync(request, ClientOptions.SocketResponseTimeout, data =>
|
await socket.SendAndWaitAsync(request, ClientOptions.SocketResponseTimeout, data =>
|
||||||
{
|
{
|
||||||
if (!HandleQueryResponse<T>(socket, request, data, out var callResult))
|
if (!HandleQueryResponse<T>(socket, request, data, out var callResult))
|
||||||
@ -336,14 +342,14 @@ namespace CryptoExchange.Net
|
|||||||
protected virtual async Task<CallResult<bool>> ConnectIfNeededAsync(SocketConnection socket, bool authenticated)
|
protected virtual async Task<CallResult<bool>> ConnectIfNeededAsync(SocketConnection socket, bool authenticated)
|
||||||
{
|
{
|
||||||
if (socket.Connected)
|
if (socket.Connected)
|
||||||
return new CallResult<bool>(true, null);
|
return new CallResult<bool>(true);
|
||||||
|
|
||||||
var connectResult = await ConnectSocketAsync(socket).ConfigureAwait(false);
|
var connectResult = await ConnectSocketAsync(socket).ConfigureAwait(false);
|
||||||
if (!connectResult)
|
if (!connectResult)
|
||||||
return new CallResult<bool>(false, connectResult.Error);
|
return new CallResult<bool>(connectResult.Error!);
|
||||||
|
|
||||||
if (!authenticated || socket.Authenticated)
|
if (!authenticated || socket.Authenticated)
|
||||||
return new CallResult<bool>(true, null);
|
return new CallResult<bool>(true);
|
||||||
|
|
||||||
var result = await AuthenticateSocketAsync(socket).ConfigureAwait(false);
|
var result = await AuthenticateSocketAsync(socket).ConfigureAwait(false);
|
||||||
if (!result)
|
if (!result)
|
||||||
@ -351,11 +357,11 @@ namespace CryptoExchange.Net
|
|||||||
await socket.CloseAsync().ConfigureAwait(false);
|
await socket.CloseAsync().ConfigureAwait(false);
|
||||||
log.Write(LogLevel.Warning, $"Socket {socket.Socket.Id} authentication failed");
|
log.Write(LogLevel.Warning, $"Socket {socket.Socket.Id} authentication failed");
|
||||||
result.Error!.Message = "Authentication failed: " + result.Error.Message;
|
result.Error!.Message = "Authentication failed: " + result.Error.Message;
|
||||||
return new CallResult<bool>(false, result.Error);
|
return new CallResult<bool>(result.Error);
|
||||||
}
|
}
|
||||||
|
|
||||||
socket.Authenticated = true;
|
socket.Authenticated = true;
|
||||||
return new CallResult<bool>(true, null);
|
return new CallResult<bool>(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -532,11 +538,11 @@ namespace CryptoExchange.Net
|
|||||||
if (await socketConnection.Socket.ConnectAsync().ConfigureAwait(false))
|
if (await socketConnection.Socket.ConnectAsync().ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
sockets.TryAdd(socketConnection.Socket.Id, socketConnection);
|
sockets.TryAdd(socketConnection.Socket.Id, socketConnection);
|
||||||
return new CallResult<bool>(true, null);
|
return new CallResult<bool>(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
socketConnection.Socket.Dispose();
|
socketConnection.Socket.Dispose();
|
||||||
return new CallResult<bool>(false, new CantConnectError());
|
return new CallResult<bool>(new CantConnectError());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -34,7 +34,7 @@ namespace CryptoExchange.Net
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Options for this client
|
/// Options for this client
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public RestApiClientOptions Options { get; }
|
public new RestApiClientOptions Options => (RestApiClientOptions)base.Options;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// List of rate limiters
|
/// List of rate limiters
|
||||||
@ -48,8 +48,6 @@ namespace CryptoExchange.Net
|
|||||||
/// <param name="apiOptions">The Api client options</param>
|
/// <param name="apiOptions">The Api client options</param>
|
||||||
public RestApiClient(BaseRestClientOptions options, RestApiClientOptions apiOptions): base(options, apiOptions)
|
public RestApiClient(BaseRestClientOptions options, RestApiClientOptions apiOptions): base(options, apiOptions)
|
||||||
{
|
{
|
||||||
Options = apiOptions;
|
|
||||||
|
|
||||||
var rateLimiters = new List<IRateLimiter>();
|
var rateLimiters = new List<IRateLimiter>();
|
||||||
foreach (var rateLimiter in apiOptions.RateLimiters)
|
foreach (var rateLimiter in apiOptions.RateLimiters)
|
||||||
rateLimiters.Add(rateLimiter);
|
rateLimiters.Add(rateLimiter);
|
||||||
@ -70,7 +68,7 @@ namespace CryptoExchange.Net
|
|||||||
if (!timeSyncParams.SyncTime || (DateTime.UtcNow - timeSyncParams.TimeSyncState.LastSyncTime < TimeSpan.FromHours(1)))
|
if (!timeSyncParams.SyncTime || (DateTime.UtcNow - timeSyncParams.TimeSyncState.LastSyncTime < TimeSpan.FromHours(1)))
|
||||||
{
|
{
|
||||||
timeSyncParams.TimeSyncState.Semaphore.Release();
|
timeSyncParams.TimeSyncState.Semaphore.Release();
|
||||||
return new WebCallResult<bool>(null, null, true, null);
|
return new WebCallResult<bool>(null, null, null, null, null, null, null, true, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
var localTime = DateTime.UtcNow;
|
var localTime = DateTime.UtcNow;
|
||||||
@ -108,7 +106,7 @@ namespace CryptoExchange.Net
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new WebCallResult<bool>(null, null, true, null);
|
return new WebCallResult<bool>(null, null, null, null, null, null, null, true, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,11 +7,6 @@ namespace CryptoExchange.Net
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class SocketApiClient : BaseApiClient
|
public abstract class SocketApiClient : BaseApiClient
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// The options for this client
|
|
||||||
/// </summary>
|
|
||||||
internal ApiClientOptions Options { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -19,8 +14,6 @@ namespace CryptoExchange.Net
|
|||||||
/// <param name="apiOptions">The Api client options</param>
|
/// <param name="apiOptions">The Api client options</param>
|
||||||
public SocketApiClient(BaseClientOptions options, ApiClientOptions apiOptions): base(options, apiOptions)
|
public SocketApiClient(BaseClientOptions options, ApiClientOptions apiOptions): base(options, apiOptions)
|
||||||
{
|
{
|
||||||
Options = apiOptions;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
|
|
||||||
namespace CryptoExchange.Net.Objects
|
namespace CryptoExchange.Net.Objects
|
||||||
{
|
{
|
||||||
@ -36,16 +38,6 @@ namespace CryptoExchange.Net.Objects
|
|||||||
{
|
{
|
||||||
return obj?.Success == true;
|
return obj?.Success == true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Create an error result
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="error"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static WebCallResult CreateErrorResult(Error error)
|
|
||||||
{
|
|
||||||
return new WebCallResult(null, null, error);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -62,22 +54,36 @@ namespace CryptoExchange.Net.Objects
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The original data returned by the call, only available when `OutputOriginalData` is set to `true` in the client options
|
/// The original data returned by the call, only available when `OutputOriginalData` is set to `true` in the client options
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string? OriginalData { get; set; }
|
public string? OriginalData { get; internal set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="data"></param>
|
/// <param name="data"></param>
|
||||||
|
/// <param name="originalData"></param>
|
||||||
/// <param name="error"></param>
|
/// <param name="error"></param>
|
||||||
#pragma warning disable 8618
|
#pragma warning disable 8618
|
||||||
public CallResult([AllowNull]T data, Error? error): base(error)
|
protected CallResult([AllowNull]T data, string? originalData, Error? error): base(error)
|
||||||
#pragma warning restore 8618
|
#pragma warning restore 8618
|
||||||
{
|
{
|
||||||
|
OriginalData = originalData;
|
||||||
#pragma warning disable 8601
|
#pragma warning disable 8601
|
||||||
Data = data;
|
Data = data;
|
||||||
#pragma warning restore 8601
|
#pragma warning restore 8601
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a new data result
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="data">The data to return</param>
|
||||||
|
public CallResult(T data) : this(data, null, null) { }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a new error result
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="error">The erro rto return</param>
|
||||||
|
public CallResult(Error error) : this(default, null, error) { }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Overwrite bool check so we can use if(callResult) instead of if(callResult.Success)
|
/// Overwrite bool check so we can use if(callResult) instead of if(callResult.Success)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -111,16 +117,6 @@ namespace CryptoExchange.Net.Objects
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Create an error result
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="error"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public new static WebCallResult<T> CreateErrorResult(Error error)
|
|
||||||
{
|
|
||||||
return new WebCallResult<T>(null, null, default, error);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Copy the WebCallResult to a new data type
|
/// Copy the WebCallResult to a new data type
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -129,7 +125,18 @@ namespace CryptoExchange.Net.Objects
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public CallResult<K> As<K>([AllowNull] K data)
|
public CallResult<K> As<K>([AllowNull] K data)
|
||||||
{
|
{
|
||||||
return new CallResult<K>(data, Error);
|
return new CallResult<K>(data, OriginalData, Error);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Copy the WebCallResult to a new data type
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="K">The new type</typeparam>
|
||||||
|
/// <param name="error">The error to return</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public CallResult<K> AsError<K>(Error error)
|
||||||
|
{
|
||||||
|
return new CallResult<K>(default, OriginalData, error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,34 +161,23 @@ namespace CryptoExchange.Net.Objects
|
|||||||
/// <param name="code">Status code</param>
|
/// <param name="code">Status code</param>
|
||||||
/// <param name="responseHeaders">Response headers</param>
|
/// <param name="responseHeaders">Response headers</param>
|
||||||
/// <param name="error">Error</param>
|
/// <param name="error">Error</param>
|
||||||
public WebCallResult(
|
private WebCallResult(
|
||||||
HttpStatusCode? code,
|
HttpStatusCode? code,
|
||||||
IEnumerable<KeyValuePair<string, IEnumerable<string>>>? responseHeaders, Error? error) : base(error)
|
IEnumerable<KeyValuePair<string, IEnumerable<string>>>? responseHeaders,
|
||||||
|
Error? error) : base(error)
|
||||||
{
|
{
|
||||||
ResponseHeaders = responseHeaders;
|
ResponseHeaders = responseHeaders;
|
||||||
ResponseStatusCode = code;
|
ResponseStatusCode = code;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create an error result
|
/// Return the result as an error result
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="code">Status code</param>
|
/// <param name="error">The error returned</param>
|
||||||
/// <param name="responseHeaders">Response headers</param>
|
|
||||||
/// <param name="error">Error</param>
|
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static WebCallResult CreateErrorResult(HttpStatusCode? code, IEnumerable<KeyValuePair<string, IEnumerable<string>>>? responseHeaders, Error error)
|
public WebCallResult AsError(Error error)
|
||||||
{
|
{
|
||||||
return new WebCallResult(code, responseHeaders, error);
|
return new WebCallResult(ResponseStatusCode, ResponseHeaders, error);
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Create an error result
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="result"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static WebCallResult CreateErrorResult(WebCallResult result)
|
|
||||||
{
|
|
||||||
return new WebCallResult(result.ResponseStatusCode, result.ResponseHeaders, result.Error);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,6 +187,26 @@ namespace CryptoExchange.Net.Objects
|
|||||||
/// <typeparam name="T"></typeparam>
|
/// <typeparam name="T"></typeparam>
|
||||||
public class WebCallResult<T>: CallResult<T>
|
public class WebCallResult<T>: CallResult<T>
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The request http method
|
||||||
|
/// </summary>
|
||||||
|
public HttpMethod? RequestMethod { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The headers sent with the request
|
||||||
|
/// </summary>
|
||||||
|
public IEnumerable<KeyValuePair<string, IEnumerable<string>>>? RequestHeaders { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The url which was requested
|
||||||
|
/// </summary>
|
||||||
|
public string? RequestUrl { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The body of the request
|
||||||
|
/// </summary>
|
||||||
|
public string? RequestBody { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The status code of the response. Note that a OK status does not always indicate success, check the Success parameter for this.
|
/// The status code of the response. Note that a OK status does not always indicate success, check the Success parameter for this.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -202,42 +218,47 @@ namespace CryptoExchange.Net.Objects
|
|||||||
public IEnumerable<KeyValuePair<string, IEnumerable<string>>>? ResponseHeaders { get; set; }
|
public IEnumerable<KeyValuePair<string, IEnumerable<string>>>? ResponseHeaders { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// The time between sending the request and receiving the response
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="code"></param>
|
public TimeSpan? ResponseTime { get; set; }
|
||||||
/// <param name="responseHeaders"></param>
|
|
||||||
/// <param name="data"></param>
|
|
||||||
/// <param name="error"></param>
|
|
||||||
public WebCallResult(
|
|
||||||
HttpStatusCode? code,
|
|
||||||
IEnumerable<KeyValuePair<string, IEnumerable<string>>>? responseHeaders,
|
|
||||||
[AllowNull] T data,
|
|
||||||
Error? error): base(data, error)
|
|
||||||
{
|
|
||||||
ResponseStatusCode = code;
|
|
||||||
ResponseHeaders = responseHeaders;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// Create a new result
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="code"></param>
|
/// <param name="code"></param>
|
||||||
/// <param name="originalData"></param>
|
|
||||||
/// <param name="responseHeaders"></param>
|
/// <param name="responseHeaders"></param>
|
||||||
|
/// <param name="originalData"></param>
|
||||||
|
/// <param name="requestUrl"></param>
|
||||||
|
/// <param name="requestBody"></param>
|
||||||
|
/// <param name="requestMethod"></param>
|
||||||
|
/// <param name="requestHeaders"></param>
|
||||||
/// <param name="data"></param>
|
/// <param name="data"></param>
|
||||||
/// <param name="error"></param>
|
/// <param name="error"></param>
|
||||||
public WebCallResult(
|
public WebCallResult(
|
||||||
HttpStatusCode? code,
|
HttpStatusCode? code,
|
||||||
IEnumerable<KeyValuePair<string, IEnumerable<string>>>? responseHeaders,
|
IEnumerable<KeyValuePair<string, IEnumerable<string>>>? responseHeaders,
|
||||||
string? originalData,
|
string? originalData,
|
||||||
|
string? requestUrl,
|
||||||
|
string? requestBody,
|
||||||
|
HttpMethod? requestMethod,
|
||||||
|
IEnumerable<KeyValuePair<string, IEnumerable<string>>>? requestHeaders,
|
||||||
[AllowNull] T data,
|
[AllowNull] T data,
|
||||||
Error? error) : base(data, error)
|
Error? error) : base(data, originalData, error)
|
||||||
{
|
{
|
||||||
OriginalData = originalData;
|
|
||||||
ResponseStatusCode = code;
|
ResponseStatusCode = code;
|
||||||
ResponseHeaders = responseHeaders;
|
ResponseHeaders = responseHeaders;
|
||||||
|
RequestUrl = requestUrl;
|
||||||
|
RequestBody = requestBody;
|
||||||
|
RequestHeaders = requestHeaders;
|
||||||
|
RequestMethod = requestMethod;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a new error result
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="error">The error</param>
|
||||||
|
public WebCallResult(Error? error) : this(null, null, null, null, null, null, null, default, error) { }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Copy the WebCallResult to a new data type
|
/// Copy the WebCallResult to a new data type
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -246,19 +267,18 @@ namespace CryptoExchange.Net.Objects
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public new WebCallResult<K> As<K>([AllowNull] K data)
|
public new WebCallResult<K> As<K>([AllowNull] K data)
|
||||||
{
|
{
|
||||||
return new WebCallResult<K>(ResponseStatusCode, ResponseHeaders, OriginalData, data, Error);
|
return new WebCallResult<K>(ResponseStatusCode, ResponseHeaders, OriginalData, RequestUrl, RequestBody, RequestMethod, RequestHeaders, data, Error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create an error result
|
/// Copy the WebCallResult to a new data type
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="code"></param>
|
/// <typeparam name="K">The new type</typeparam>
|
||||||
/// <param name="responseHeaders"></param>
|
/// <param name="error">The error returned</param>
|
||||||
/// <param name="error"></param>
|
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static WebCallResult<T> CreateErrorResult(HttpStatusCode? code, IEnumerable<KeyValuePair<string, IEnumerable<string>>>? responseHeaders, Error error)
|
public new WebCallResult<K> AsError<K>(Error error)
|
||||||
{
|
{
|
||||||
return new WebCallResult<T>(code, responseHeaders, default, error);
|
return new WebCallResult<K>(ResponseStatusCode, ResponseHeaders, OriginalData, RequestUrl, RequestBody, RequestMethod, RequestHeaders, default, error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -118,7 +118,7 @@ namespace CryptoExchange.Net.Objects
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (endpointLimit?.IgnoreOtherRateLimits == true)
|
if (endpointLimit?.IgnoreOtherRateLimits == true)
|
||||||
return new CallResult<int>(totalWaitTime, null);
|
return new CallResult<int>(totalWaitTime);
|
||||||
|
|
||||||
List<PartialEndpointRateLimiter> partialEndpointLimits;
|
List<PartialEndpointRateLimiter> partialEndpointLimits;
|
||||||
lock (_limiterLock)
|
lock (_limiterLock)
|
||||||
@ -155,7 +155,7 @@ namespace CryptoExchange.Net.Objects
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(partialEndpointLimits.Any(p => p.IgnoreOtherRateLimits))
|
if(partialEndpointLimits.Any(p => p.IgnoreOtherRateLimits))
|
||||||
return new CallResult<int>(totalWaitTime, null);
|
return new CallResult<int>(totalWaitTime);
|
||||||
|
|
||||||
ApiKeyRateLimiter? apiLimit;
|
ApiKeyRateLimiter? apiLimit;
|
||||||
lock (_limiterLock)
|
lock (_limiterLock)
|
||||||
@ -195,7 +195,7 @@ namespace CryptoExchange.Net.Objects
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((signed || apiLimit?.OnlyForSignedRequests == false) && apiLimit?.IgnoreTotalRateLimit == true)
|
if ((signed || apiLimit?.OnlyForSignedRequests == false) && apiLimit?.IgnoreTotalRateLimit == true)
|
||||||
return new CallResult<int>(totalWaitTime, null);
|
return new CallResult<int>(totalWaitTime);
|
||||||
|
|
||||||
TotalRateLimiter? totalLimit;
|
TotalRateLimiter? totalLimit;
|
||||||
lock (_limiterLock)
|
lock (_limiterLock)
|
||||||
@ -209,7 +209,7 @@ namespace CryptoExchange.Net.Objects
|
|||||||
totalWaitTime += waitResult.Data;
|
totalWaitTime += waitResult.Data;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new CallResult<int>(totalWaitTime, null);
|
return new CallResult<int>(totalWaitTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task<CallResult<int>> ProcessTopic(Log log, Limiter historyTopic, string endpoint, int requestWeight, RateLimitingBehaviour limitBehaviour, CancellationToken ct)
|
private static async Task<CallResult<int>> ProcessTopic(Log log, Limiter historyTopic, string endpoint, int requestWeight, RateLimitingBehaviour limitBehaviour, CancellationToken ct)
|
||||||
@ -221,7 +221,7 @@ namespace CryptoExchange.Net.Objects
|
|||||||
}
|
}
|
||||||
catch (OperationCanceledException)
|
catch (OperationCanceledException)
|
||||||
{
|
{
|
||||||
return new CallResult<int>(0, new CancellationRequestedError());
|
return new CallResult<int>(new CancellationRequestedError());
|
||||||
}
|
}
|
||||||
sw.Stop();
|
sw.Stop();
|
||||||
|
|
||||||
@ -253,7 +253,7 @@ namespace CryptoExchange.Net.Objects
|
|||||||
historyTopic.Semaphore.Release();
|
historyTopic.Semaphore.Release();
|
||||||
var msg = $"Request to {endpoint} failed because of rate limit `{historyTopic}`. Current weight: {currentWeight}/{historyTopic.Limit}, request weight: {requestWeight}";
|
var msg = $"Request to {endpoint} failed because of rate limit `{historyTopic}`. Current weight: {currentWeight}/{historyTopic.Limit}, request weight: {requestWeight}";
|
||||||
log.Write(LogLevel.Warning, msg);
|
log.Write(LogLevel.Warning, msg);
|
||||||
return new CallResult<int>(thisWaitTime, new RateLimitError(msg));
|
return new CallResult<int>(new RateLimitError(msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Write(LogLevel.Information, $"Request to {endpoint} waiting {thisWaitTime}ms for rate limit `{historyTopic}`. Current weight: {currentWeight}/{historyTopic.Limit}, request weight: {requestWeight}");
|
log.Write(LogLevel.Information, $"Request to {endpoint} waiting {thisWaitTime}ms for rate limit `{historyTopic}`. Current weight: {currentWeight}/{historyTopic.Limit}, request weight: {requestWeight}");
|
||||||
@ -263,7 +263,7 @@ namespace CryptoExchange.Net.Objects
|
|||||||
}
|
}
|
||||||
catch (OperationCanceledException)
|
catch (OperationCanceledException)
|
||||||
{
|
{
|
||||||
return new CallResult<int>(0, new CancellationRequestedError());
|
return new CallResult<int>(new CancellationRequestedError());
|
||||||
}
|
}
|
||||||
totalWaitTime += thisWaitTime;
|
totalWaitTime += thisWaitTime;
|
||||||
}
|
}
|
||||||
@ -277,7 +277,7 @@ namespace CryptoExchange.Net.Objects
|
|||||||
var newTime = DateTime.UtcNow;
|
var newTime = DateTime.UtcNow;
|
||||||
historyTopic.Entries.Add(new LimitEntry(newTime, requestWeight));
|
historyTopic.Entries.Add(new LimitEntry(newTime, requestWeight));
|
||||||
historyTopic.Semaphore.Release();
|
historyTopic.Semaphore.Release();
|
||||||
return new CallResult<int>(totalWaitTime, null);
|
return new CallResult<int>(totalWaitTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal struct LimitEntry
|
internal struct LimitEntry
|
||||||
|
@ -233,7 +233,7 @@ namespace CryptoExchange.Net.OrderBook
|
|||||||
if (!startResult)
|
if (!startResult)
|
||||||
{
|
{
|
||||||
Status = OrderBookStatus.Disconnected;
|
Status = OrderBookStatus.Disconnected;
|
||||||
return new CallResult<bool>(false, startResult.Error);
|
return new CallResult<bool>(startResult.Error!);
|
||||||
}
|
}
|
||||||
|
|
||||||
_subscription = startResult.Data;
|
_subscription = startResult.Data;
|
||||||
@ -252,7 +252,7 @@ namespace CryptoExchange.Net.OrderBook
|
|||||||
|
|
||||||
_subscription.ConnectionRestored += async time => await ResyncAsync().ConfigureAwait(false);
|
_subscription.ConnectionRestored += async time => await ResyncAsync().ConfigureAwait(false);
|
||||||
Status = OrderBookStatus.Synced;
|
Status = OrderBookStatus.Synced;
|
||||||
return new CallResult<bool>(true, null);
|
return new CallResult<bool>(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
@ -273,7 +273,7 @@ namespace CryptoExchange.Net.OrderBook
|
|||||||
public CallResult<decimal> CalculateAverageFillPrice(decimal quantity, OrderBookEntryType type)
|
public CallResult<decimal> CalculateAverageFillPrice(decimal quantity, OrderBookEntryType type)
|
||||||
{
|
{
|
||||||
if (Status != OrderBookStatus.Synced)
|
if (Status != OrderBookStatus.Synced)
|
||||||
return new CallResult<decimal>(0, new InvalidOperationError($"{nameof(CalculateAverageFillPrice)} is not available when book is not in Synced state"));
|
return new CallResult<decimal>(new InvalidOperationError($"{nameof(CalculateAverageFillPrice)} is not available when book is not in Synced state"));
|
||||||
|
|
||||||
var totalCost = 0m;
|
var totalCost = 0m;
|
||||||
var totalAmount = 0m;
|
var totalAmount = 0m;
|
||||||
@ -286,7 +286,7 @@ namespace CryptoExchange.Net.OrderBook
|
|||||||
while (amountLeft > 0)
|
while (amountLeft > 0)
|
||||||
{
|
{
|
||||||
if (step == list.Count)
|
if (step == list.Count)
|
||||||
return new CallResult<decimal>(0, new InvalidOperationError("Quantity is larger than order in the order book"));
|
return new CallResult<decimal>(new InvalidOperationError("Quantity is larger than order in the order book"));
|
||||||
|
|
||||||
var element = list.ElementAt(step);
|
var element = list.ElementAt(step);
|
||||||
var stepAmount = Math.Min(element.Value.Quantity, amountLeft);
|
var stepAmount = Math.Min(element.Value.Quantity, amountLeft);
|
||||||
@ -297,7 +297,7 @@ namespace CryptoExchange.Net.OrderBook
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new CallResult<decimal>(Math.Round(totalCost / totalAmount, 8), null);
|
return new CallResult<decimal>(Math.Round(totalCost / totalAmount, 8));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -466,12 +466,12 @@ namespace CryptoExchange.Net.OrderBook
|
|||||||
while (!bookSet && Status == OrderBookStatus.Syncing)
|
while (!bookSet && Status == OrderBookStatus.Syncing)
|
||||||
{
|
{
|
||||||
if ((DateTime.UtcNow - startWait).TotalMilliseconds > timeout)
|
if ((DateTime.UtcNow - startWait).TotalMilliseconds > timeout)
|
||||||
return new CallResult<bool>(false, new ServerError("Timeout while waiting for data"));
|
return new CallResult<bool>(new ServerError("Timeout while waiting for data"));
|
||||||
|
|
||||||
await Task.Delay(10).ConfigureAwait(false);
|
await Task.Delay(10).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new CallResult<bool>(true, null);
|
return new CallResult<bool>(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -530,7 +530,7 @@ namespace CryptoExchange.Net.Sockets
|
|||||||
internal async Task<CallResult<bool>> ResubscribeAsync(SocketSubscription socketSubscription)
|
internal async Task<CallResult<bool>> ResubscribeAsync(SocketSubscription socketSubscription)
|
||||||
{
|
{
|
||||||
if (!Socket.IsOpen)
|
if (!Socket.IsOpen)
|
||||||
return new CallResult<bool>(false, new UnknownError("Socket is not connected"));
|
return new CallResult<bool>(new UnknownError("Socket is not connected"));
|
||||||
|
|
||||||
return await socketClient.SubscribeAndWaitAsync(this, socketSubscription.Request!, socketSubscription).ConfigureAwait(false);
|
return await socketClient.SubscribeAndWaitAsync(this, socketSubscription.Request!, socketSubscription).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user