using CryptoExchange.Net.SharedApis;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Net;
using System.Net.Http;
using System.Text;
namespace CryptoExchange.Net.Objects
{
///
/// The result of an operation
///
public class CallResult
{
///
/// An error if the call didn't succeed, will always be filled if Success = false
///
public Error? Error { get; internal set; }
///
/// Whether the call was successful
///
public bool Success => Error == null;
///
/// ctor
///
///
public CallResult(Error? error)
{
Error = error;
}
///
/// Overwrite bool check so we can use if(callResult) instead of if(callResult.Success)
///
///
public static implicit operator bool(CallResult obj)
{
return obj?.Success == true;
}
///
public override string ToString()
{
return Success ? $"Success" : $"Error: {Error}";
}
}
///
/// The result of an operation
///
///
public class CallResult: CallResult
{
///
/// The data returned by the call, only available when Success = true
///
public T Data { get; internal set; }
///
/// The original data returned by the call, only available when `OutputOriginalData` is set to `true` in the client options
///
public string? OriginalData { get; internal set; }
///
/// ctor
///
///
///
///
#pragma warning disable 8618
public 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 error to return
public CallResult(Error error) : this(default, null, error) { }
///
/// Create a new error result
///
/// The error to return
/// The original response data
public CallResult(Error error, string? originalData) : this(default, originalData, error) { }
///
/// Overwrite bool check so we can use if(callResult) instead of if(callResult.Success)
///
///
public static implicit operator bool(CallResult obj)
{
return obj?.Success == true;
}
///
/// Whether the call was successful or not. Useful for nullability checking.
///
/// The data returned by the call.
/// on failure.
/// true when succeeded, false otherwise.
public bool GetResultOrError([MaybeNullWhen(false)] out T data, [NotNullWhen(false)] out Error? error)
{
if (Success)
{
data = Data!;
error = null;
return true;
}
else
{
data = default;
error = Error!;
return false;
}
}
///
/// Copy the WebCallResult to a new data type
///
/// The new type
/// The data of the new type
///
public CallResult As([AllowNull] K data)
{
return new CallResult(data, OriginalData, Error);
}
///
/// Copy as a dataless result
///
///
public CallResult AsDataless()
{
return new CallResult(null);
}
///
/// Copy as a dataless result
///
///
public CallResult AsDatalessError(Error error)
{
return new CallResult(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);
}
///
public override string ToString()
{
return Success ? $"Success" : $"Error: {Error}";
}
}
///
/// The result of a request
///
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 request id
///
public int? RequestId { 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.
///
public HttpStatusCode? ResponseStatusCode { get; set; }
///
/// The response headers
///
public IEnumerable>>? ResponseHeaders { get; set; }
///
/// The time between sending the request and receiving the response
///
public TimeSpan? ResponseTime { get; set; }
///
/// ctor
///
///
///
///
///
///
///
///
///
///
public WebCallResult(
HttpStatusCode? code,
IEnumerable>>? responseHeaders,
TimeSpan? responseTime,
int? requestId,
string? requestUrl,
string? requestBody,
HttpMethod? requestMethod,
IEnumerable>>? requestHeaders,
Error? error) : base(error)
{
ResponseStatusCode = code;
ResponseHeaders = responseHeaders;
ResponseTime = responseTime;
RequestId = requestId;
RequestUrl = requestUrl;
RequestBody = requestBody;
RequestHeaders = requestHeaders;
RequestMethod = requestMethod;
}
///
/// ctor
///
///
public WebCallResult(Error error): base(error) { }
///
/// Return the result as an error result
///
/// The error returned
///
public WebCallResult AsError(Error error)
{
return new WebCallResult(ResponseStatusCode, ResponseHeaders, ResponseTime, RequestId, RequestUrl, RequestBody, RequestMethod, RequestHeaders, error);
}
///
/// Copy the WebCallResult to a new data type
///
/// The new type
/// The data of the new type
///
public WebCallResult As([AllowNull] K data)
{
return new WebCallResult(ResponseStatusCode, ResponseHeaders, ResponseTime, 0, null, RequestId, RequestUrl, RequestBody, RequestMethod, RequestHeaders, ResultDataSource.Server, data, Error);
}
///
/// Copy the WebCallResult to an ExchangeWebResult of a new data type
///
/// The new type
/// The exchange
/// Trade mode the result applies to
/// The data
///
public ExchangeWebResult AsExchangeResult(string exchange, TradingMode tradeMode, [AllowNull] K data)
{
return new ExchangeWebResult(exchange, tradeMode, this.As(data));
}
///
/// Copy the WebCallResult to an ExchangeWebResult of a new data type
///
/// The new type
/// The exchange
/// Trade modes the result applies to
/// The data
///
public ExchangeWebResult AsExchangeResult(string exchange, TradingMode[]? tradeModes, [AllowNull] K data)
{
return new ExchangeWebResult(exchange, tradeModes, this.As(data));
}
///
/// Copy the WebCallResult to a new data type
///
/// The new type
/// The error returned
///
public WebCallResult AsError(Error error)
{
return new WebCallResult(ResponseStatusCode, ResponseHeaders, ResponseTime, 0, null, RequestId, RequestUrl, RequestBody, RequestMethod, RequestHeaders, ResultDataSource.Server, default, error);
}
///
public override string ToString()
{
return (Success ? $"Success" : $"Error: {Error}") + $" in {ResponseTime}";
}
}
///
/// The result of a request
///
///
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 request id
///
public int? RequestId { 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.
///
public HttpStatusCode? ResponseStatusCode { get; set; }
///
/// Length in bytes of the response
///
public long? ResponseLength { get; set; }
///
/// The response headers
///
public IEnumerable>>? ResponseHeaders { get; set; }
///
/// The time between sending the request and receiving the response
///
public TimeSpan? ResponseTime { get; set; }
///
/// The data source of this result
///
public ResultDataSource DataSource { get; set; } = ResultDataSource.Server;
///
/// Create a new result
///
///
///
///
///
///
///
///
///
///
///
///
///
///
public WebCallResult(
HttpStatusCode? code,
IEnumerable>>? responseHeaders,
TimeSpan? responseTime,
long? responseLength,
string? originalData,
int? requestId,
string? requestUrl,
string? requestBody,
HttpMethod? requestMethod,
IEnumerable>>? requestHeaders,
ResultDataSource dataSource,
[AllowNull] T data,
Error? error) : base(data, originalData, error)
{
ResponseStatusCode = code;
ResponseHeaders = responseHeaders;
ResponseTime = responseTime;
ResponseLength = responseLength;
RequestId = requestId;
RequestUrl = requestUrl;
RequestBody = requestBody;
RequestHeaders = requestHeaders;
RequestMethod = requestMethod;
DataSource = dataSource;
}
///
/// Copy as a dataless result
///
///
public new WebCallResult AsDataless()
{
return new WebCallResult(ResponseStatusCode, ResponseHeaders, ResponseTime, RequestId, RequestUrl, RequestBody, RequestMethod, RequestHeaders, Error);
}
///
/// Copy as a dataless result
///
///
public new WebCallResult AsDatalessError(Error error)
{
return new WebCallResult(ResponseStatusCode, ResponseHeaders, ResponseTime, RequestId, RequestUrl, RequestBody, RequestMethod, RequestHeaders, error);
}
///
/// Create a new error result
///
/// The error
public WebCallResult(Error? error) : this(null, null, null, null, null, null, null, null, null, null, ResultDataSource.Server, default, error) { }
///
/// Copy the WebCallResult to a new data type
///
/// The new type
/// The data of the new type
///
public new WebCallResult As([AllowNull] K data)
{
return new WebCallResult(ResponseStatusCode, ResponseHeaders, ResponseTime, ResponseLength, OriginalData, RequestId, RequestUrl, RequestBody, RequestMethod, RequestHeaders, DataSource, data, Error);
}
///
/// Copy the WebCallResult to a new data type
///
/// The new type
/// The error returned
///
public new WebCallResult AsError(Error error)
{
return new WebCallResult(ResponseStatusCode, ResponseHeaders, ResponseTime, ResponseLength, OriginalData, RequestId, RequestUrl, RequestBody, RequestMethod, RequestHeaders, DataSource, default, error);
}
///
/// Copy the WebCallResult to an ExchangeWebResult of a new data type
///
/// The exchange
/// Trade mode the result applies to
///
public ExchangeWebResult AsExchangeResult(string exchange, TradingMode tradeMode)
{
return new ExchangeWebResult(exchange, tradeMode, this);
}
///
/// Copy the WebCallResult to an ExchangeWebResult of a new data type
///
/// The exchange
/// Trade modes the result applies to
///
public ExchangeWebResult AsExchangeResult(string exchange, TradingMode[] tradeModes)
{
return new ExchangeWebResult(exchange, tradeModes, this);
}
///
/// Copy the WebCallResult to an ExchangeWebResult of a new data type
///
/// The new type
/// The exchange
/// Trade mode the result applies to
/// Data
/// Next page token
///
public ExchangeWebResult AsExchangeResult(string exchange, TradingMode tradeMode, [AllowNull] K data, INextPageToken? nextPageToken = null)
{
return new ExchangeWebResult(exchange, tradeMode, As(data), nextPageToken);
}
///
/// Copy the WebCallResult to an ExchangeWebResult of a new data type
///
/// The new type
/// The exchange
/// Trade modes the result applies to
/// Data
/// Next page token
///
public ExchangeWebResult AsExchangeResult(string exchange, TradingMode[]? tradeModes, [AllowNull] K data, INextPageToken? nextPageToken = null)
{
return new ExchangeWebResult(exchange, tradeModes, As(data), nextPageToken);
}
///
/// Copy the WebCallResult to an ExchangeWebResult with a specific error
///
/// The new type
/// The exchange
/// The error returned
///
public ExchangeWebResult AsExchangeError(string exchange, Error error)
{
return new ExchangeWebResult(exchange, null, AsError(error));
}
///
/// Return a copy of this result with data source set to cache
///
///
internal WebCallResult Cached()
{
return new WebCallResult(ResponseStatusCode, ResponseHeaders, ResponseTime, ResponseLength, OriginalData, RequestId, RequestUrl, RequestBody, RequestMethod, RequestHeaders, ResultDataSource.Cache, Data, Error);
}
///
public override string ToString()
{
var sb = new StringBuilder();
sb.Append(Success ? $"Success response" : $"Error response: {Error}");
if (ResponseLength != null)
sb.Append($", {ResponseLength} bytes");
if (ResponseTime != null)
sb.Append($" received in {Math.Round(ResponseTime?.TotalMilliseconds ?? 0)}ms");
return sb.ToString();
}
}
}