using CryptoExchange.Net.Objects.Errors; using System; namespace CryptoExchange.Net.Objects { /// /// Base class for errors /// public abstract class Error { private int? _code; /// /// The int error code the server returned; or the http status code int value if there was no error code.
///
/// Note:
/// The property should be used for more generic error checking; it might contain a string error code if the server does not return an int code. ///
public int? Code { get { if (_code.HasValue) return _code; return int.TryParse(ErrorCode, out var r) ? r : null; } set { _code = value; } } /// /// The error code returned by the server /// public string? ErrorCode { get; set; } /// /// The error description /// public string? ErrorDescription { get; set; } /// /// Error type /// public ErrorType ErrorType { get; set; } /// /// Whether the error is transient and can be retried /// public bool IsTransient { get; set; } /// /// The server message for the error that occurred /// public string? Message { get; set; } /// /// Underlying exception /// public Exception? Exception { get; set; } /// /// ctor /// protected Error(string? errorCode, ErrorInfo errorInfo, Exception? exception) { ErrorCode = errorCode; ErrorType = errorInfo.ErrorType; Message = errorInfo.Message; ErrorDescription = errorInfo.ErrorDescription; IsTransient = errorInfo.IsTransient; Exception = exception; } /// /// String representation /// /// public override string ToString() { return Code != null ? $"[{GetType().Name}.{ErrorType}] {Code}: {GetErrorDescription()}" : $"[{GetType().Name}.{ErrorType}] {GetErrorDescription()}"; } private string GetErrorDescription() { if (!string.IsNullOrEmpty(Message)) return Message!; if (ErrorDescription != "Unknown error" || Exception == null) return ErrorDescription!; return Exception.Message; } } /// /// Cant reach server error /// public class CantConnectError : Error { /// /// Default error info /// protected static readonly ErrorInfo _errorInfo = new ErrorInfo(ErrorType.UnableToConnect, false, "Can't connect to the server"); /// /// ctor /// public CantConnectError() : base(null, _errorInfo, null) { } /// /// ctor /// public CantConnectError(Exception? exception) : base(null, _errorInfo, exception) { } /// /// ctor /// protected CantConnectError(ErrorInfo info, Exception? exception) : base(null, info, exception) { } } /// /// No api credentials provided while trying to access a private endpoint /// public class NoApiCredentialsError : Error { /// /// Default error info /// protected static readonly ErrorInfo _errorInfo = new ErrorInfo(ErrorType.MissingCredentials, false, "No credentials provided for private endpoint, set the `ApiCredentials` option in the client configuration"); /// /// ctor /// public NoApiCredentialsError() : base(null, _errorInfo, null) { } /// /// ctor /// protected NoApiCredentialsError(ErrorInfo info, Exception? exception) : base(null, info, exception) { } } /// /// Error returned by the server /// public class ServerError : Error { /// /// ctor /// public ServerError(ErrorType type, string message, Exception? exception = null) : base(null, new ErrorInfo(type, message), exception) { } /// /// ctor /// public ServerError(ErrorInfo errorInfo, Exception? exception = null) : base(null, errorInfo, exception) { } /// /// ctor /// public ServerError(int errorCode, ErrorInfo errorInfo, Exception? exception = null) : this(errorCode.ToString(), errorInfo, exception) { } /// /// ctor /// public ServerError(string errorCode, ErrorInfo errorInfo, Exception? exception = null) : base(errorCode, errorInfo, exception) { } } /// /// Web error returned by the server /// public class WebError : Error { /// /// Default error info /// protected static readonly ErrorInfo _errorInfo = new ErrorInfo(ErrorType.NetworkError, true, "Failed to complete the request to the server due to a network error"); /// /// ctor /// public WebError(string? message = null, Exception? exception = null) : base(null, _errorInfo with { Message = (message?.Length > 0 ? _errorInfo.Message + ": " + message : _errorInfo.Message) }, exception) { } } /// /// Timeout error waiting for a response from the server /// public class TimeoutError : Error { /// /// Default error info /// protected static readonly ErrorInfo _errorInfo = new ErrorInfo(ErrorType.Timeout, false, "Failed to receive a response from the server in time"); /// /// ctor /// public TimeoutError(string? message = null, Exception? exception = null) : base(null, _errorInfo with { Message = (message?.Length > 0 ? _errorInfo.Message + ": " + message : _errorInfo.Message) }, exception) { } } /// /// Error while deserializing data /// public class DeserializeError : Error { /// /// Default error info /// protected static readonly ErrorInfo _errorInfo = new ErrorInfo(ErrorType.DeserializationFailed, false, "Failed to deserialize data"); /// /// ctor /// public DeserializeError(string? message = null, Exception? exception = null) : base(null, _errorInfo with { Message = message?.Length > 0 ? message : _errorInfo.Message }, exception) { } } /// /// An invalid parameter has been provided /// public class ArgumentError : Error { /// /// Default error info for missing parameter /// protected static readonly ErrorInfo _missingInfo = new ErrorInfo(ErrorType.MissingParameter, false, "Missing parameter"); /// /// Default error info for invalid parameter /// protected static readonly ErrorInfo _invalidInfo = new ErrorInfo(ErrorType.InvalidParameter, false, "Invalid parameter"); /// /// ctor /// public static ArgumentError Missing(string parameterName, string? message = null) => new ArgumentError(_missingInfo with { Message = message == null ? $"{_missingInfo.Message} '{parameterName}'" : $"{_missingInfo.Message} '{parameterName}': {message}" }, null); /// /// ctor /// public static ArgumentError Invalid(string parameterName, string message) => new ArgumentError(_invalidInfo with { Message = $"{_invalidInfo.Message} '{parameterName}': {message}" }, null); /// /// ctor /// protected ArgumentError(ErrorInfo info, Exception? exception) : base(null, info, exception) { } } /// /// Rate limit exceeded (client side) /// public abstract class BaseRateLimitError : Error { /// /// When the request can be retried /// public DateTime? RetryAfter { get; set; } /// /// ctor /// protected BaseRateLimitError(ErrorInfo errorInfo, Exception? exception) : base(null, errorInfo, exception) { } } /// /// Rate limit exceeded (client side) /// public class ClientRateLimitError : BaseRateLimitError { /// /// Default error info /// protected static readonly ErrorInfo _errorInfo = new ErrorInfo(ErrorType.RateLimitRequest, false, "Client rate limit exceeded"); /// /// ctor /// public ClientRateLimitError(string? message = null, Exception? exception = null) : base(_errorInfo with { Message = (message?.Length > 0 ? _errorInfo.Message + ": " + message : _errorInfo.Message) }, exception) { } /// /// ctor /// protected ClientRateLimitError(ErrorInfo info, Exception? exception) : base(info, exception) { } } /// /// Rate limit exceeded (server side) /// public class ServerRateLimitError : BaseRateLimitError { /// /// Default error info /// protected static readonly ErrorInfo _errorInfo = new ErrorInfo(ErrorType.RateLimitRequest, false, "Server rate limit exceeded"); /// /// ctor /// public ServerRateLimitError(string? message = null, Exception? exception = null) : base(_errorInfo with { Message = (message?.Length > 0 ? _errorInfo.Message + ": " + message : _errorInfo.Message) }, exception) { } /// /// ctor /// protected ServerRateLimitError(ErrorInfo info, Exception? exception) : base(info, exception) { } } /// /// Cancellation requested /// public class CancellationRequestedError : Error { /// /// Default error info /// protected static readonly ErrorInfo _errorInfo = new ErrorInfo(ErrorType.CancellationRequested, false, "Cancellation requested"); /// /// ctor /// public CancellationRequestedError(Exception? exception = null) : base(null, _errorInfo, null) { } /// /// ctor /// protected CancellationRequestedError(ErrorInfo info, Exception? exception) : base(null, info, exception) { } } /// /// Invalid operation requested /// public class InvalidOperationError : Error { /// /// Default error info /// protected static readonly ErrorInfo _errorInfo = new ErrorInfo(ErrorType.InvalidOperation, false, "Operation invalid"); /// /// ctor /// public InvalidOperationError(string message) : base(null, _errorInfo with { Message = message }, null) { } /// /// ctor /// protected InvalidOperationError(ErrorInfo info, Exception? exception) : base(null, info, exception) { } } }