diff --git a/CryptoExchange.Net/Clients/BaseClient.cs b/CryptoExchange.Net/Clients/BaseClient.cs index e2390ac..c015ccd 100644 --- a/CryptoExchange.Net/Clients/BaseClient.cs +++ b/CryptoExchange.Net/Clients/BaseClient.cs @@ -93,28 +93,28 @@ namespace CryptoExchange.Net { var info = "Empty data object received"; log.Write(LogLevel.Error, info); - return new CallResult(null, new DeserializeError(info, data)); + return new CallResult(new DeserializeError(info, data)); } try { - return new CallResult(JToken.Parse(data), null); + return new CallResult(JToken.Parse(data)); } catch (JsonReaderException jre) { var info = $"Deserialize JsonReaderException: {jre.Message}, Path: {jre.Path}, LineNumber: {jre.LineNumber}, LinePosition: {jre.LinePosition}"; - return new CallResult(null, new DeserializeError(info, data)); + return new CallResult(new DeserializeError(info, data)); } catch (JsonSerializationException jse) { var info = $"Deserialize JsonSerializationException: {jse.Message}"; - return new CallResult(null, new DeserializeError(info, data)); + return new CallResult(new DeserializeError(info, data)); } catch (Exception ex) { var exceptionInfo = ex.ToLogString(); var info = $"Deserialize Unknown Exception: {exceptionInfo}"; - return new CallResult(null, new DeserializeError(info, data)); + return new CallResult(new DeserializeError(info, data)); } } @@ -132,7 +132,7 @@ namespace CryptoExchange.Net if (!tokenResult) { log.Write(LogLevel.Error, tokenResult.Error!.Message); - return new CallResult(default, tokenResult.Error); + return new CallResult( tokenResult.Error); } return Deserialize(tokenResult.Data, serializer, requestId); @@ -152,26 +152,26 @@ namespace CryptoExchange.Net try { - return new CallResult(obj.ToObject(serializer), null); + return new CallResult(obj.ToObject(serializer)!); } catch (JsonReaderException jre) { 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); - return new CallResult(default, new DeserializeError(info, obj)); + return new CallResult(new DeserializeError(info, obj)); } catch (JsonSerializationException jse) { var info = $"{(requestId != null ? $"[{requestId}] " : "")}Deserialize JsonSerializationException: {jse.Message} data: {obj}"; log.Write(LogLevel.Error, info); - return new CallResult(default, new DeserializeError(info, obj)); + return new CallResult(new DeserializeError(info, obj)); } catch (Exception ex) { var exceptionInfo = ex.ToLogString(); var info = $"{(requestId != null ? $"[{requestId}] " : "")}Deserialize Unknown Exception: {exceptionInfo}, data: {obj}"; log.Write(LogLevel.Error, info); - return new CallResult(default, new DeserializeError(info, obj)); + return new CallResult(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 // 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); - return new CallResult(serializer.Deserialize(jsonReader), null); + return new CallResult(serializer.Deserialize(jsonReader)!); } catch (JsonReaderException jre) { @@ -222,7 +222,7 @@ namespace CryptoExchange.Net else 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}"); - return new CallResult(default, new DeserializeError($"Deserialize JsonReaderException: {jre.Message}, Path: {jre.Path}, LineNumber: {jre.LineNumber}, LinePosition: {jre.LinePosition}", data)); + return new CallResult(new DeserializeError($"Deserialize JsonReaderException: {jre.Message}, Path: {jre.Path}, LineNumber: {jre.LineNumber}, LinePosition: {jre.LinePosition}", data)); } catch (JsonSerializationException jse) { @@ -236,7 +236,7 @@ namespace CryptoExchange.Net data = "[Data only available in Debug LogLevel]"; log.Write(LogLevel.Error, $"{(requestId != null ? $"[{requestId}] " : "")}Deserialize JsonSerializationException: {jse.Message}, data: {data}"); - return new CallResult(default, new DeserializeError($"Deserialize JsonSerializationException: {jse.Message}", data)); + return new CallResult(new DeserializeError($"Deserialize JsonSerializationException: {jse.Message}", data)); } catch (Exception ex) { @@ -250,7 +250,7 @@ namespace CryptoExchange.Net var exceptionInfo = ex.ToLogString(); log.Write(LogLevel.Error, $"{(requestId != null ? $"[{requestId}] " : "")}Deserialize Unknown Exception: {exceptionInfo}, data: {data}"); - return new CallResult(default, new DeserializeError($"Deserialize Unknown Exception: {exceptionInfo}", data)); + return new CallResult(new DeserializeError($"Deserialize Unknown Exception: {exceptionInfo}", data)); } } diff --git a/CryptoExchange.Net/Clients/BaseRestClient.cs b/CryptoExchange.Net/Clients/BaseRestClient.cs index a08a55f..7449c27 100644 --- a/CryptoExchange.Net/Clients/BaseRestClient.cs +++ b/CryptoExchange.Net/Clients/BaseRestClient.cs @@ -136,7 +136,7 @@ namespace CryptoExchange.Net if (signed && apiClient.AuthenticationProvider == null) { log.Write(LogLevel.Warning, $"[{requestId}] Request {uri.AbsolutePath} failed because no ApiCredentials were provided"); - return new WebCallResult(null, null, null, new NoApiCredentialsError()); + return new WebCallResult(new NoApiCredentialsError()); } 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); if (!limitResult.Success) - return new WebCallResult(null, null, null, limitResult.Error); + return new WebCallResult(limitResult.Error!); } 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 var parseResult = ValidateJson(data); if (!parseResult.Success) - return WebCallResult.CreateErrorResult(response.StatusCode, response.ResponseHeaders, parseResult.Error!); + return new WebCallResult(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 var error = await TryParseErrorAsync(parseResult.Data).ConfigureAwait(false); if (error != null) - return WebCallResult.CreateErrorResult(response.StatusCode, response.ResponseHeaders, error); + return new WebCallResult(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 var deserializeResult = Deserialize(parseResult.Data, deserializer, request.RequestId); - return new WebCallResult(response.StatusCode, response.ResponseHeaders, ClientOptions.OutputOriginalData ? data: null, deserializeResult.Data, deserializeResult.Error); + return new WebCallResult(response.StatusCode, response.ResponseHeaders, ClientOptions.OutputOriginalData ? data: null, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), deserializeResult.Data, deserializeResult.Error); } else { @@ -214,7 +214,7 @@ namespace CryptoExchange.Net responseStream.Close(); response.Close(); - return new WebCallResult(statusCode, headers, ClientOptions.OutputOriginalData ? desResult.OriginalData : null, desResult.Data, desResult.Error); + return new WebCallResult(statusCode, headers, ClientOptions.OutputOriginalData ? desResult.OriginalData : null, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), desResult.Data, desResult.Error); } } else @@ -229,7 +229,7 @@ namespace CryptoExchange.Net var error = parseResult.Success ? ParseErrorResponse(parseResult.Data) : parseResult.Error!; if(error.Code == null || error.Code == 0) error.Code = (int)response.StatusCode; - return new WebCallResult(statusCode, headers, default, error); + return new WebCallResult(statusCode, headers, data, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), default, error); } } catch (HttpRequestException requestException) @@ -237,7 +237,7 @@ namespace CryptoExchange.Net // Request exception, can't reach server for instance var exceptionInfo = requestException.ToLogString(); log.Write(LogLevel.Warning, $"[{request.RequestId}] Request exception: " + exceptionInfo); - return new WebCallResult(null, null, default, new WebError(exceptionInfo)); + return new WebCallResult(null, null, null, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), default, new WebError(exceptionInfo)); } catch (OperationCanceledException canceledException) { @@ -245,13 +245,13 @@ namespace CryptoExchange.Net { // Cancellation token canceled by caller log.Write(LogLevel.Warning, $"[{request.RequestId}] Request canceled by cancellation token"); - return new WebCallResult(null, null, default, new CancellationRequestedError()); + return new WebCallResult(null, null, null, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), default, new CancellationRequestedError()); } else { // Request timed out log.Write(LogLevel.Warning, $"[{request.RequestId}] Request timed out: " + canceledException.ToLogString()); - return new WebCallResult(null, null, default, new WebError($"[{request.RequestId}] Request timed out")); + return new WebCallResult(null, null, null, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), default, new WebError($"[{request.RequestId}] Request timed out")); } } } diff --git a/CryptoExchange.Net/Clients/BaseSocketClient.cs b/CryptoExchange.Net/Clients/BaseSocketClient.cs index 0d6317b..5450735 100644 --- a/CryptoExchange.Net/Clients/BaseSocketClient.cs +++ b/CryptoExchange.Net/Clients/BaseSocketClient.cs @@ -163,7 +163,7 @@ namespace CryptoExchange.Net } catch (OperationCanceledException) { - return new CallResult(null, new CancellationRequestedError()); + return new CallResult(new CancellationRequestedError()); } try @@ -184,7 +184,7 @@ namespace CryptoExchange.Net var connectResult = await ConnectIfNeededAsync(socketConnection, authenticated).ConfigureAwait(false); if (!connectResult) - return new CallResult(null, connectResult.Error); + return new CallResult(connectResult.Error!); if (needsConnecting) 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) { log.Write(LogLevel.Information, $"Socket {socketConnection.Socket.Id} has been paused, can't subscribe at this moment"); - return new CallResult(default, new ServerError("Socket is paused")); + return new CallResult( new ServerError("Socket is paused")); } if (request != null) @@ -208,7 +208,7 @@ namespace CryptoExchange.Net if (!subResult) { await socketConnection.CloseAsync(subscription).ConfigureAwait(false); - return new CallResult(null, subResult.Error); + return new CallResult(subResult.Error!); } } else @@ -226,7 +226,7 @@ namespace CryptoExchange.Net await socketConnection.CloseAsync(subscription).ConfigureAwait(false); }, false); } - return new CallResult(new UpdateSubscription(socketConnection, subscription), null); + return new CallResult(new UpdateSubscription(socketConnection, subscription)); } /// @@ -242,9 +242,15 @@ namespace CryptoExchange.Net await socketConnection.SendAndWaitAsync(request, ClientOptions.SocketResponseTimeout, data => HandleSubscriptionResponse(socketConnection, subscription, request, data, out callResult)).ConfigureAwait(false); if (callResult?.Success == true) + { subscription.Confirmed = true; + return new CallResult(true); + } - return new CallResult(callResult?.Success ?? false, callResult == null ? new ServerError("No response on subscription request received"): callResult.Error); + if(callResult== null) + return new CallResult(new ServerError("No response on subscription request received")); + + return new CallResult(callResult.Error!); } /// @@ -286,7 +292,7 @@ namespace CryptoExchange.Net var connectResult = await ConnectIfNeededAsync(socketConnection, authenticated).ConfigureAwait(false); if (!connectResult) - return new CallResult(default, connectResult.Error); + return new CallResult(connectResult.Error!); } finally { @@ -299,7 +305,7 @@ namespace CryptoExchange.Net if (socketConnection.PausedActivity) { log.Write(LogLevel.Information, $"Socket {socketConnection.Socket.Id} has been paused, can't send query at this moment"); - return new CallResult(default, new ServerError("Socket is paused")); + return new CallResult(new ServerError("Socket is paused")); } return await QueryAndWaitAsync(socketConnection, request).ConfigureAwait(false); @@ -314,7 +320,7 @@ namespace CryptoExchange.Net /// protected virtual async Task> QueryAndWaitAsync(SocketConnection socket, object request) { - var dataResult = new CallResult(default, new ServerError("No response on query received")); + var dataResult = new CallResult(new ServerError("No response on query received")); await socket.SendAndWaitAsync(request, ClientOptions.SocketResponseTimeout, data => { if (!HandleQueryResponse(socket, request, data, out var callResult)) @@ -336,14 +342,14 @@ namespace CryptoExchange.Net protected virtual async Task> ConnectIfNeededAsync(SocketConnection socket, bool authenticated) { if (socket.Connected) - return new CallResult(true, null); + return new CallResult(true); var connectResult = await ConnectSocketAsync(socket).ConfigureAwait(false); if (!connectResult) - return new CallResult(false, connectResult.Error); + return new CallResult(connectResult.Error!); if (!authenticated || socket.Authenticated) - return new CallResult(true, null); + return new CallResult(true); var result = await AuthenticateSocketAsync(socket).ConfigureAwait(false); if (!result) @@ -351,11 +357,11 @@ namespace CryptoExchange.Net await socket.CloseAsync().ConfigureAwait(false); log.Write(LogLevel.Warning, $"Socket {socket.Socket.Id} authentication failed"); result.Error!.Message = "Authentication failed: " + result.Error.Message; - return new CallResult(false, result.Error); + return new CallResult(result.Error); } socket.Authenticated = true; - return new CallResult(true, null); + return new CallResult(true); } /// @@ -532,11 +538,11 @@ namespace CryptoExchange.Net if (await socketConnection.Socket.ConnectAsync().ConfigureAwait(false)) { sockets.TryAdd(socketConnection.Socket.Id, socketConnection); - return new CallResult(true, null); + return new CallResult(true); } socketConnection.Socket.Dispose(); - return new CallResult(false, new CantConnectError()); + return new CallResult(new CantConnectError()); } /// diff --git a/CryptoExchange.Net/Clients/RestApiClient.cs b/CryptoExchange.Net/Clients/RestApiClient.cs index 00ef774..3f3f2b2 100644 --- a/CryptoExchange.Net/Clients/RestApiClient.cs +++ b/CryptoExchange.Net/Clients/RestApiClient.cs @@ -34,7 +34,7 @@ namespace CryptoExchange.Net /// /// Options for this client /// - public RestApiClientOptions Options { get; } + public new RestApiClientOptions Options => (RestApiClientOptions)base.Options; /// /// List of rate limiters @@ -48,8 +48,6 @@ namespace CryptoExchange.Net /// The Api client options public RestApiClient(BaseRestClientOptions options, RestApiClientOptions apiOptions): base(options, apiOptions) { - Options = apiOptions; - var rateLimiters = new List(); foreach (var rateLimiter in apiOptions.RateLimiters) rateLimiters.Add(rateLimiter); @@ -70,7 +68,7 @@ namespace CryptoExchange.Net if (!timeSyncParams.SyncTime || (DateTime.UtcNow - timeSyncParams.TimeSyncState.LastSyncTime < TimeSpan.FromHours(1))) { timeSyncParams.TimeSyncState.Semaphore.Release(); - return new WebCallResult(null, null, true, null); + return new WebCallResult(null, null, null, null, null, null, null, true, null); } var localTime = DateTime.UtcNow; @@ -108,7 +106,7 @@ namespace CryptoExchange.Net } } - return new WebCallResult(null, null, true, null); + return new WebCallResult(null, null, null, null, null, null, null, true, null); } } } diff --git a/CryptoExchange.Net/Clients/SocketApiClient.cs b/CryptoExchange.Net/Clients/SocketApiClient.cs index 05fc465..dd14bfa 100644 --- a/CryptoExchange.Net/Clients/SocketApiClient.cs +++ b/CryptoExchange.Net/Clients/SocketApiClient.cs @@ -7,11 +7,6 @@ namespace CryptoExchange.Net /// public abstract class SocketApiClient : BaseApiClient { - /// - /// The options for this client - /// - internal ApiClientOptions Options { get; } - /// /// ctor /// @@ -19,8 +14,6 @@ namespace CryptoExchange.Net /// The Api client options public SocketApiClient(BaseClientOptions options, ApiClientOptions apiOptions): base(options, apiOptions) { - Options = apiOptions; } - } } diff --git a/CryptoExchange.Net/Objects/CallResult.cs b/CryptoExchange.Net/Objects/CallResult.cs index f498d19..91b46f9 100644 --- a/CryptoExchange.Net/Objects/CallResult.cs +++ b/CryptoExchange.Net/Objects/CallResult.cs @@ -1,6 +1,8 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Net; +using System.Net.Http; namespace CryptoExchange.Net.Objects { @@ -36,16 +38,6 @@ namespace CryptoExchange.Net.Objects { return obj?.Success == true; } - - /// - /// Create an error result - /// - /// - /// - public static WebCallResult CreateErrorResult(Error error) - { - return new WebCallResult(null, null, error); - } } /// @@ -62,22 +54,36 @@ namespace CryptoExchange.Net.Objects /// /// The original data returned by the call, only available when `OutputOriginalData` is set to `true` in the client options /// - public string? OriginalData { get; set; } + public string? OriginalData { get; internal set; } /// /// ctor /// /// + /// /// #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 { + OriginalData = originalData; #pragma warning disable 8601 Data = data; #pragma warning restore 8601 } + /// + /// Create a new data result + /// + /// The data to return + public CallResult(T data) : this(data, null, null) { } + + /// + /// Create a new error result + /// + /// The erro rto return + public CallResult(Error error) : this(default, null, error) { } + /// /// Overwrite bool check so we can use if(callResult) instead of if(callResult.Success) /// @@ -111,16 +117,6 @@ namespace CryptoExchange.Net.Objects } } - /// - /// Create an error result - /// - /// - /// - public new static WebCallResult CreateErrorResult(Error error) - { - return new WebCallResult(null, null, default, error); - } - /// /// Copy the WebCallResult to a new data type /// @@ -129,7 +125,18 @@ namespace CryptoExchange.Net.Objects /// public CallResult As([AllowNull] K data) { - return new CallResult(data, Error); + return new CallResult(data, OriginalData, Error); + } + + /// + /// Copy the WebCallResult to a new data type + /// + /// The new type + /// The error to return + /// + public CallResult AsError(Error error) + { + return new CallResult(default, OriginalData, error); } } @@ -154,34 +161,23 @@ namespace CryptoExchange.Net.Objects /// Status code /// Response headers /// Error - public WebCallResult( + private WebCallResult( HttpStatusCode? code, - IEnumerable>>? responseHeaders, Error? error) : base(error) + IEnumerable>>? responseHeaders, + Error? error) : base(error) { ResponseHeaders = responseHeaders; ResponseStatusCode = code; } /// - /// Create an error result + /// Return the result as an error result /// - /// Status code - /// Response headers - /// Error + /// The error returned /// - public static WebCallResult CreateErrorResult(HttpStatusCode? code, IEnumerable>>? responseHeaders, Error error) + public WebCallResult AsError(Error error) { - return new WebCallResult(code, responseHeaders, error); - } - - /// - /// Create an error result - /// - /// - /// - public static WebCallResult CreateErrorResult(WebCallResult result) - { - return new WebCallResult(result.ResponseStatusCode, result.ResponseHeaders, result.Error); + return new WebCallResult(ResponseStatusCode, ResponseHeaders, error); } } @@ -191,6 +187,26 @@ namespace CryptoExchange.Net.Objects /// public class WebCallResult: CallResult { + /// + /// The request http method + /// + public HttpMethod? RequestMethod { get; set; } + + /// + /// The headers sent with the request + /// + public IEnumerable>>? RequestHeaders { get; set; } + + /// + /// The url which was requested + /// + public string? RequestUrl { get; set; } + + /// + /// The body of the request + /// + public string? RequestBody { get; set; } + /// /// The status code of the response. Note that a OK status does not always indicate success, check the Success parameter for this. /// @@ -200,44 +216,49 @@ namespace CryptoExchange.Net.Objects /// The response headers /// public IEnumerable>>? ResponseHeaders { get; set; } - - /// - /// ctor - /// - /// - /// - /// - /// - public WebCallResult( - HttpStatusCode? code, - IEnumerable>>? responseHeaders, - [AllowNull] T data, - Error? error): base(data, error) - { - ResponseStatusCode = code; - ResponseHeaders = responseHeaders; - } /// - /// ctor + /// The time between sending the request and receiving the response + /// + public TimeSpan? ResponseTime { get; set; } + + /// + /// Create a new result /// /// - /// /// + /// + /// + /// + /// + /// /// /// public WebCallResult( HttpStatusCode? code, IEnumerable>>? responseHeaders, string? originalData, + string? requestUrl, + string? requestBody, + HttpMethod? requestMethod, + IEnumerable>>? requestHeaders, [AllowNull] T data, - Error? error) : base(data, error) + Error? error) : base(data, originalData, error) { - OriginalData = originalData; ResponseStatusCode = code; ResponseHeaders = responseHeaders; + RequestUrl = requestUrl; + RequestBody = requestBody; + RequestHeaders = requestHeaders; + RequestMethod = requestMethod; } + /// + /// Create a new error result + /// + /// The error + public WebCallResult(Error? error) : this(null, null, null, null, null, null, null, default, error) { } + /// /// Copy the WebCallResult to a new data type /// @@ -246,19 +267,18 @@ namespace CryptoExchange.Net.Objects /// public new WebCallResult As([AllowNull] K data) { - return new WebCallResult(ResponseStatusCode, ResponseHeaders, OriginalData, data, Error); + return new WebCallResult(ResponseStatusCode, ResponseHeaders, OriginalData, RequestUrl, RequestBody, RequestMethod, RequestHeaders, data, Error); } /// - /// Create an error result + /// Copy the WebCallResult to a new data type /// - /// - /// - /// + /// The new type + /// The error returned /// - public static WebCallResult CreateErrorResult(HttpStatusCode? code, IEnumerable>>? responseHeaders, Error error) + public new WebCallResult AsError(Error error) { - return new WebCallResult(code, responseHeaders, default, error); + return new WebCallResult(ResponseStatusCode, ResponseHeaders, OriginalData, RequestUrl, RequestBody, RequestMethod, RequestHeaders, default, error); } } } diff --git a/CryptoExchange.Net/Objects/RateLimiter.cs b/CryptoExchange.Net/Objects/RateLimiter.cs index dc0b4e8..9b5f2ae 100644 --- a/CryptoExchange.Net/Objects/RateLimiter.cs +++ b/CryptoExchange.Net/Objects/RateLimiter.cs @@ -118,7 +118,7 @@ namespace CryptoExchange.Net.Objects } if (endpointLimit?.IgnoreOtherRateLimits == true) - return new CallResult(totalWaitTime, null); + return new CallResult(totalWaitTime); List partialEndpointLimits; lock (_limiterLock) @@ -155,7 +155,7 @@ namespace CryptoExchange.Net.Objects } if(partialEndpointLimits.Any(p => p.IgnoreOtherRateLimits)) - return new CallResult(totalWaitTime, null); + return new CallResult(totalWaitTime); ApiKeyRateLimiter? apiLimit; lock (_limiterLock) @@ -195,7 +195,7 @@ namespace CryptoExchange.Net.Objects } if ((signed || apiLimit?.OnlyForSignedRequests == false) && apiLimit?.IgnoreTotalRateLimit == true) - return new CallResult(totalWaitTime, null); + return new CallResult(totalWaitTime); TotalRateLimiter? totalLimit; lock (_limiterLock) @@ -209,7 +209,7 @@ namespace CryptoExchange.Net.Objects totalWaitTime += waitResult.Data; } - return new CallResult(totalWaitTime, null); + return new CallResult(totalWaitTime); } private static async Task> ProcessTopic(Log log, Limiter historyTopic, string endpoint, int requestWeight, RateLimitingBehaviour limitBehaviour, CancellationToken ct) @@ -221,7 +221,7 @@ namespace CryptoExchange.Net.Objects } catch (OperationCanceledException) { - return new CallResult(0, new CancellationRequestedError()); + return new CallResult(new CancellationRequestedError()); } sw.Stop(); @@ -253,7 +253,7 @@ namespace CryptoExchange.Net.Objects historyTopic.Semaphore.Release(); var msg = $"Request to {endpoint} failed because of rate limit `{historyTopic}`. Current weight: {currentWeight}/{historyTopic.Limit}, request weight: {requestWeight}"; log.Write(LogLevel.Warning, msg); - return new CallResult(thisWaitTime, new RateLimitError(msg)); + return new CallResult(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}"); @@ -263,7 +263,7 @@ namespace CryptoExchange.Net.Objects } catch (OperationCanceledException) { - return new CallResult(0, new CancellationRequestedError()); + return new CallResult(new CancellationRequestedError()); } totalWaitTime += thisWaitTime; } @@ -277,7 +277,7 @@ namespace CryptoExchange.Net.Objects var newTime = DateTime.UtcNow; historyTopic.Entries.Add(new LimitEntry(newTime, requestWeight)); historyTopic.Semaphore.Release(); - return new CallResult(totalWaitTime, null); + return new CallResult(totalWaitTime); } internal struct LimitEntry diff --git a/CryptoExchange.Net/OrderBook/SymbolOrderBook.cs b/CryptoExchange.Net/OrderBook/SymbolOrderBook.cs index 69569e3..d4a6df3 100644 --- a/CryptoExchange.Net/OrderBook/SymbolOrderBook.cs +++ b/CryptoExchange.Net/OrderBook/SymbolOrderBook.cs @@ -233,7 +233,7 @@ namespace CryptoExchange.Net.OrderBook if (!startResult) { Status = OrderBookStatus.Disconnected; - return new CallResult(false, startResult.Error); + return new CallResult(startResult.Error!); } _subscription = startResult.Data; @@ -252,7 +252,7 @@ namespace CryptoExchange.Net.OrderBook _subscription.ConnectionRestored += async time => await ResyncAsync().ConfigureAwait(false); Status = OrderBookStatus.Synced; - return new CallResult(true, null); + return new CallResult(true); } /// @@ -273,7 +273,7 @@ namespace CryptoExchange.Net.OrderBook public CallResult CalculateAverageFillPrice(decimal quantity, OrderBookEntryType type) { if (Status != OrderBookStatus.Synced) - return new CallResult(0, new InvalidOperationError($"{nameof(CalculateAverageFillPrice)} is not available when book is not in Synced state")); + return new CallResult(new InvalidOperationError($"{nameof(CalculateAverageFillPrice)} is not available when book is not in Synced state")); var totalCost = 0m; var totalAmount = 0m; @@ -286,7 +286,7 @@ namespace CryptoExchange.Net.OrderBook while (amountLeft > 0) { if (step == list.Count) - return new CallResult(0, new InvalidOperationError("Quantity is larger than order in the order book")); + return new CallResult(new InvalidOperationError("Quantity is larger than order in the order book")); var element = list.ElementAt(step); var stepAmount = Math.Min(element.Value.Quantity, amountLeft); @@ -297,7 +297,7 @@ namespace CryptoExchange.Net.OrderBook } } - return new CallResult(Math.Round(totalCost / totalAmount, 8), null); + return new CallResult(Math.Round(totalCost / totalAmount, 8)); } /// @@ -466,12 +466,12 @@ namespace CryptoExchange.Net.OrderBook while (!bookSet && Status == OrderBookStatus.Syncing) { if ((DateTime.UtcNow - startWait).TotalMilliseconds > timeout) - return new CallResult(false, new ServerError("Timeout while waiting for data")); + return new CallResult(new ServerError("Timeout while waiting for data")); await Task.Delay(10).ConfigureAwait(false); } - return new CallResult(true, null); + return new CallResult(true); } /// diff --git a/CryptoExchange.Net/Sockets/SocketConnection.cs b/CryptoExchange.Net/Sockets/SocketConnection.cs index db639a1..6959973 100644 --- a/CryptoExchange.Net/Sockets/SocketConnection.cs +++ b/CryptoExchange.Net/Sockets/SocketConnection.cs @@ -530,7 +530,7 @@ namespace CryptoExchange.Net.Sockets internal async Task> ResubscribeAsync(SocketSubscription socketSubscription) { if (!Socket.IsOpen) - return new CallResult(false, new UnknownError("Socket is not connected")); + return new CallResult(new UnknownError("Socket is not connected")); return await socketClient.SubscribeAndWaitAsync(this, socketSubscription.Request!, socketSubscription).ConfigureAwait(false); }