deribit_base/error/
codes.rs

1/******************************************************************************
2   Author: Joaquín Béjar García
3   Email: jb@taunais.com
4   Date: 22/7/25
5******************************************************************************/
6use pretty_simple_display::{DebugPretty, DisplaySimple};
7
8use serde::{Deserialize, Serialize};
9
10/// Deribit RPC Error Codes
11///
12/// Complete enumeration of all error codes returned by the Deribit API
13/// as documented in the official API documentation v2.1.1
14#[derive(DebugPretty, DisplaySimple, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
15#[serde(from = "i32", into = "i32")]
16pub enum DeribitErrorCode {
17    /// Success, No error
18    Success,
19    /// Authorization issue, invalid or absent signature etc.
20    AuthorizationRequired,
21    /// Some general failure, no public information available
22    Error,
23    /// Order quantity is too low
24    QtyTooLow,
25    /// Rejection, order overlap is found and self-trading is not enabled
26    OrderOverlap,
27    /// Attempt to operate with order that can't be found by specified id or label
28    OrderNotFound,
29    /// Price is too low, limit defines current limit for the operation
30    PriceTooLow,
31    /// Price is too low for current index, limit defines current bottom limit
32    PriceTooLow4Idx,
33    /// Price is too high, limit defines current up limit for the operation
34    PriceTooHigh,
35    /// Account has not enough funds for the operation
36    NotEnoughFunds,
37    /// Attempt of doing something with closed order
38    AlreadyClosed,
39    /// This price is not allowed for some reason
40    PriceNotAllowed,
41    /// Operation for an instrument which order book had been closed
42    BookClosed,
43    /// Total limit of open orders has been exceeded (PME users)
44    PmeMaxTotalOpenOrders,
45    /// Limit of count of futures' open orders has been exceeded (PME users)
46    PmeMaxFutureOpenOrders,
47    /// Limit of count of options' open orders has been exceeded (PME users)
48    PmeMaxOptionOpenOrders,
49    /// Limit of size for futures has been exceeded (PME users)
50    PmeMaxFutureOpenOrdersSize,
51    /// Limit of size for options has been exceeded (PME users)
52    PmeMaxOptionOpenOrdersSize,
53    /// Limit of size for futures has been exceeded (non-PME users)
54    NonPmeMaxFuturePositionSize,
55    /// Trading is temporary locked by the admin
56    LockedByAdmin,
57    /// Instrument name is not valid
58    InvalidOrUnsupportedInstrument,
59    /// Amount is not valid
60    InvalidAmount,
61    /// Quantity was not recognized as a valid number (for API v1)
62    InvalidQuantity,
63    /// Price was not recognized as a valid number
64    InvalidPrice,
65    /// max_show parameter was not recognized as a valid number
66    InvalidMaxShow,
67    /// Order id is missing or its format was not recognized as valid
68    InvalidOrderId,
69    /// Extra precision of the price is not supported
70    PricePrecisionExceeded,
71    /// Futures contract amount was not recognized as integer
72    NonIntegerContractAmount,
73    /// Allowed request rate has been exceeded
74    TooManyRequests,
75    /// Attempt to operate with not own order
76    NotOwnerOfOrder,
77    /// REST request where Websocket is expected
78    MustBeWebsocketRequest,
79    /// Some of the arguments are not recognized as valid
80    InvalidArgsForInstrument,
81    /// Total cost is too low
82    WholeCostTooLow,
83    /// Method is not implemented yet
84    NotImplemented,
85    /// Trigger price is too high
86    TriggerPriceTooHigh,
87    /// Trigger price is too low
88    TriggerPriceTooLow,
89    /// Max Show Amount is not valid
90    InvalidMaxShowAmount,
91    /// Limit of total size for short options positions has been exceeded (non-PME users)
92    NonPmeTotalShortOptionsPositionsSize,
93    /// Limit of open risk reducing orders has been reached (PME users)
94    PmeMaxRiskReducingOrders,
95    /// User does not have sufficient spot reserves or negative impact on portfolio margin
96    NotEnoughFundsInCurrency,
97    /// Request can't be processed right now and should be retried
98    Retry,
99    /// Settlement is in progress
100    SettlementInProgress,
101    /// Price has to be rounded to an instrument tick size
102    PriceWrongTick,
103    /// Trigger Price has to be rounded to an instrument tick size
104    TriggerPriceWrongTick,
105    /// Liquidation order can't be cancelled
106    CanNotCancelLiquidationOrder,
107    /// Liquidation order can't be edited
108    CanNotEditLiquidationOrder,
109    /// Reached limit of pending Matching Engine requests for user
110    MatchingEngineQueueFull,
111    /// The requested operation is not available on this server
112    NotOnThisServer,
113    /// Enabling Cancel On Disconnect for the connection failed
114    CancelOnDisconnectFailed,
115    /// The client has sent too many public requests that have not yet been executed
116    TooManyConcurrentRequests,
117    /// Spot trading is disabled for users in reduce only mode
118    DisabledWhilePositionLock,
119    /// This request is not allowed in regards to the filled order
120    AlreadyFilled,
121    /// Total limit of open orders on spot instruments has been exceeded
122    MaxSpotOpenOrders,
123    /// Price modification for post only order is not possible
124    PostOnlyPriceModificationNotPossible,
125    /// Limit of quantity per currency for spot instruments has been exceeded
126    MaxSpotOrderQuantity,
127    /// Some invalid input has been detected
128    InvalidArguments,
129    /// Some rejects which are not considered as very often
130    OtherReject,
131    /// Some errors which are not considered as very often
132    OtherError,
133    /// Allowed amount of trigger orders has been exceeded
134    NoMoreTriggers,
135    /// Invalid trigger price in relation to the last trade, index or market price
136    InvalidTriggerPrice,
137    /// Instrument already not available for trading
138    OutdatedInstrumentForIvOrder,
139    /// Advanced orders are not available for futures
140    NoAdvForFutures,
141    /// Advanced post-only orders are not supported yet
142    NoAdvPostonly,
143    /// Advanced order properties can't be set if the order is not advanced
144    NotAdvOrder,
145    /// Permission for the operation has been denied
146    PermissionDenied,
147    /// Bad argument has been passed
148    BadArgument,
149    /// Attempt to do open order operations with the not open order
150    NotOpenOrder,
151    /// Event name has not been recognized
152    InvalidEvent,
153    /// At several minutes to instrument expiration, advanced IV orders are not allowed
154    OutdatedInstrument,
155    /// The specified combination of arguments is not supported
156    UnsupportedArgCombination,
157    /// Wrong Max Show for options
158    WrongMaxShowForOption,
159    /// Several bad arguments have been passed
160    BadArguments,
161    /// Request has not been parsed properly
162    BadRequest,
163    /// System is under maintenance
164    SystemMaintenance,
165    /// Subscription error
166    SubscribeErrorUnsubscribed,
167    /// Specified transfer is not found
168    TransferNotFound,
169    /// Request rejected due to reject_post_only flag
170    PostOnlyReject,
171    /// Post only flag not allowed for given order type
172    PostOnlyNotAllowed,
173    /// Unauthenticated public requests were temporarily disabled
174    UnauthenticatedPublicRequestsTemporarilyDisabled,
175    /// Invalid address
176    InvalidAddr,
177    /// Invalid address for the transfer
178    InvalidTransferAddress,
179    /// The address already exists
180    AddressAlreadyExist,
181    /// Limit of allowed addresses has been reached
182    MaxAddrCountExceeded,
183    /// Some unhandled error on server
184    InternalServerError,
185    /// Deposit address creation has been disabled by admin
186    DisabledDepositAddressCreation,
187    /// Withdrawal instead of transfer
188    AddressBelongsToUser,
189    /// Deposit address not specified
190    NoDepositAddress,
191    /// Account locked
192    AccountLocked,
193    /// Limit of subaccounts is reached
194    TooManySubaccounts,
195    /// The input is not allowed as the name of subaccount
196    WrongSubaccountName,
197    /// The number of failed login attempts is limited
198    LoginOverLimit,
199    /// The number of registration requests is limited
200    RegistrationOverLimit,
201    /// The country is banned (possibly via IP check)
202    CountryIsBanned,
203    /// Transfer is not allowed
204    TransferNotAllowed,
205    /// Too many failed security key authorizations
206    SecurityKeyAuthorizationOverLimit,
207    /// Invalid credentials have been used
208    InvalidCredentials,
209    /// Password confirmation error
210    PwdMatchError,
211    /// Invalid Security Code
212    SecurityError,
213    /// User's security code has been changed or wrong
214    UserNotFound,
215    /// Request failed because of invalid input or internal failure
216    RequestFailed,
217    /// Wrong or expired authorization token or bad signature
218    Unauthorized,
219    /// Invalid input, missing value
220    ValueRequired,
221    /// Input is too short
222    ValueTooShort,
223    /// Subaccount restrictions
224    UnavailableInSubaccount,
225    /// Unsupported or invalid phone number
226    InvalidPhoneNumber,
227    /// SMS sending failed -- phone number is wrong
228    CannotSendSms,
229    /// Invalid SMS code
230    InvalidSmsCode,
231    /// Invalid input
232    InvalidInput,
233    /// Invalid content type of the request
234    InvalidContentType,
235    /// Closed, expired order book
236    OrderbookClosed,
237    /// Instrument is not found, invalid instrument name
238    NotFound,
239    /// Not enough permissions to execute the request, forbidden
240    Forbidden,
241    /// API method temporarily switched off by the administrator
242    MethodSwitchedOffByAdmin,
243    /// The requested service is not responding or processing takes too long
244    TemporarilyUnavailable,
245    /// Order has been rejected due to the MMP trigger
246    MmpTrigger,
247    /// API method allowed only for verified users
248    VerificationRequired,
249    /// Request allowed only for orders uniquely identified by given label
250    NonUniqueOrderLabel,
251    /// Maximal number of tokens allowed reached
252    NoMoreSecurityKeysAllowed,
253    /// Limit of active combo books was reached
254    ActiveComboLimitReached,
255    /// Action is temporarily unavailable for combo books
256    UnavailableForComboBooks,
257    /// KYC verification data is insufficient for external service provider
258    IncompleteKycData,
259    /// User is not a MMP user
260    MmpRequired,
261    /// Cancel-on-Disconnect is not enabled for the connection
262    CodNotEnabled,
263    /// Quotes are still frozen after previous cancel
264    QuotesFrozen,
265    /// Error returned after the user tried to edit/delete an API key with insufficient scope
266    ScopeExceeded,
267    /// Method is currently not available
268    Unavailable,
269    /// Request was cancelled by the user with other api request
270    RequestCancelledByUser,
271    /// Edit request was replaced by other one
272    Replaced,
273    /// Raw subscriptions are not available for unauthorized requests
274    RawSubscriptionsNotAvailableForUnauthorized,
275    /// The client cannot execute the request yet, should wait
276    MovePositionsOverLimit,
277    /// The coupon has already been used by current account
278    CouponAlreadyUsed,
279    /// Sharing of KYC data with a third party provider was already initiated
280    KycTransferAlreadyInitiated,
281    /// Unknown error code
282    Unknown(i32),
283}
284
285impl DeribitErrorCode {
286    /// Get the numeric error code
287    pub fn code(&self) -> i32 {
288        self.clone().into()
289    }
290
291    /// Get the short error message
292    pub fn message(&self) -> &'static str {
293        match self {
294            Self::Success => "success",
295            Self::AuthorizationRequired => "authorization_required",
296            Self::Error => "error",
297            Self::QtyTooLow => "qty_too_low",
298            Self::OrderOverlap => "order_overlap",
299            Self::OrderNotFound => "order_not_found",
300            Self::PriceTooLow => "price_too_low",
301            Self::PriceTooLow4Idx => "price_too_low4idx",
302            Self::PriceTooHigh => "price_too_high",
303            Self::NotEnoughFunds => "not_enough_funds",
304            Self::AlreadyClosed => "already_closed",
305            Self::PriceNotAllowed => "price_not_allowed",
306            Self::BookClosed => "book_closed",
307            Self::PmeMaxTotalOpenOrders => "pme_max_total_open_orders",
308            Self::PmeMaxFutureOpenOrders => "pme_max_future_open_orders",
309            Self::PmeMaxOptionOpenOrders => "pme_max_option_open_orders",
310            Self::PmeMaxFutureOpenOrdersSize => "pme_max_future_open_orders_size",
311            Self::PmeMaxOptionOpenOrdersSize => "pme_max_option_open_orders_size",
312            Self::NonPmeMaxFuturePositionSize => "non_pme_max_future_position_size",
313            Self::LockedByAdmin => "locked_by_admin",
314            Self::InvalidOrUnsupportedInstrument => "invalid_or_unsupported_instrument",
315            Self::InvalidAmount => "invalid_amount",
316            Self::InvalidQuantity => "invalid_quantity",
317            Self::InvalidPrice => "invalid_price",
318            Self::InvalidMaxShow => "invalid_max_show",
319            Self::InvalidOrderId => "invalid_order_id",
320            Self::PricePrecisionExceeded => "price_precision_exceeded",
321            Self::NonIntegerContractAmount => "non_integer_contract_amount",
322            Self::TooManyRequests => "too_many_requests",
323            Self::NotOwnerOfOrder => "not_owner_of_order",
324            Self::MustBeWebsocketRequest => "must_be_websocket_request",
325            Self::InvalidArgsForInstrument => "invalid_args_for_instrument",
326            Self::WholeCostTooLow => "whole_cost_too_low",
327            Self::NotImplemented => "not_implemented",
328            Self::TriggerPriceTooHigh => "trigger_price_too_high",
329            Self::TriggerPriceTooLow => "trigger_price_too_low",
330            Self::InvalidMaxShowAmount => "invalid_max_show_amount",
331            Self::NonPmeTotalShortOptionsPositionsSize => {
332                "non_pme_total_short_options_positions_size"
333            }
334            Self::PmeMaxRiskReducingOrders => "pme_max_risk_reducing_orders",
335            Self::NotEnoughFundsInCurrency => "not_enough_funds_in_currency",
336            Self::Retry => "retry",
337            Self::SettlementInProgress => "settlement_in_progress",
338            Self::PriceWrongTick => "price_wrong_tick",
339            Self::TriggerPriceWrongTick => "trigger_price_wrong_tick",
340            Self::CanNotCancelLiquidationOrder => "can_not_cancel_liquidation_order",
341            Self::CanNotEditLiquidationOrder => "can_not_edit_liquidation_order",
342            Self::MatchingEngineQueueFull => "matching_engine_queue_full",
343            Self::NotOnThisServer => "not_on_this_server",
344            Self::CancelOnDisconnectFailed => "cancel_on_disconnect_failed",
345            Self::TooManyConcurrentRequests => "too_many_concurrent_requests",
346            Self::DisabledWhilePositionLock => "disabled_while_position_lock",
347            Self::AlreadyFilled => "already_filled",
348            Self::MaxSpotOpenOrders => "max_spot_open_orders",
349            Self::PostOnlyPriceModificationNotPossible => {
350                "post_only_price_modification_not_possible"
351            }
352            Self::MaxSpotOrderQuantity => "max_spot_order_quantity",
353            Self::InvalidArguments => "invalid_arguments",
354            Self::OtherReject => "other_reject",
355            Self::OtherError => "other_error",
356            Self::NoMoreTriggers => "no_more_triggers",
357            Self::InvalidTriggerPrice => "invalid_trigger_price",
358            Self::OutdatedInstrumentForIvOrder => "outdated_instrument_for_IV_order",
359            Self::NoAdvForFutures => "no_adv_for_futures",
360            Self::NoAdvPostonly => "no_adv_postonly",
361            Self::NotAdvOrder => "not_adv_order",
362            Self::PermissionDenied => "permission_denied",
363            Self::BadArgument => "bad_argument",
364            Self::NotOpenOrder => "not_open_order",
365            Self::InvalidEvent => "invalid_event",
366            Self::OutdatedInstrument => "outdated_instrument",
367            Self::UnsupportedArgCombination => "unsupported_arg_combination",
368            Self::WrongMaxShowForOption => "wrong_max_show_for_option",
369            Self::BadArguments => "bad_arguments",
370            Self::BadRequest => "bad_request",
371            Self::SystemMaintenance => "system_maintenance",
372            Self::SubscribeErrorUnsubscribed => "subscribe_error_unsubscribed",
373            Self::TransferNotFound => "transfer_not_found",
374            Self::PostOnlyReject => "post_only_reject",
375            Self::PostOnlyNotAllowed => "post_only_not_allowed",
376            Self::UnauthenticatedPublicRequestsTemporarilyDisabled => {
377                "unauthenticated_public_requests_temporarily_disabled"
378            }
379            Self::InvalidAddr => "invalid_addr",
380            Self::InvalidTransferAddress => "invalid_transfer_address",
381            Self::AddressAlreadyExist => "address_already_exist",
382            Self::MaxAddrCountExceeded => "max_addr_count_exceeded",
383            Self::InternalServerError => "internal_server_error",
384            Self::DisabledDepositAddressCreation => "disabled_deposit_address_creation",
385            Self::AddressBelongsToUser => "address_belongs_to_user",
386            Self::NoDepositAddress => "no_deposit_address",
387            Self::AccountLocked => "account_locked",
388            Self::TooManySubaccounts => "too_many_subaccounts",
389            Self::WrongSubaccountName => "wrong_subaccount_name",
390            Self::LoginOverLimit => "login_over_limit",
391            Self::RegistrationOverLimit => "registration_over_limit",
392            Self::CountryIsBanned => "country_is_banned",
393            Self::TransferNotAllowed => "transfer_not_allowed",
394            Self::SecurityKeyAuthorizationOverLimit => "security_key_authorization_over_limit",
395            Self::InvalidCredentials => "invalid_credentials",
396            Self::PwdMatchError => "pwd_match_error",
397            Self::SecurityError => "security_error",
398            Self::UserNotFound => "user_not_found",
399            Self::RequestFailed => "request_failed",
400            Self::Unauthorized => "unauthorized",
401            Self::ValueRequired => "value_required",
402            Self::ValueTooShort => "value_too_short",
403            Self::UnavailableInSubaccount => "unavailable_in_subaccount",
404            Self::InvalidPhoneNumber => "invalid_phone_number",
405            Self::CannotSendSms => "cannot_send_sms",
406            Self::InvalidSmsCode => "invalid_sms_code",
407            Self::InvalidInput => "invalid_input",
408            Self::InvalidContentType => "invalid_content_type",
409            Self::OrderbookClosed => "orderbook_closed",
410            Self::NotFound => "not_found",
411            Self::Forbidden => "forbidden",
412            Self::MethodSwitchedOffByAdmin => "method_switched_off_by_admin",
413            Self::TemporarilyUnavailable => "temporarily_unavailable",
414            Self::MmpTrigger => "mmp_trigger",
415            Self::VerificationRequired => "verification_required",
416            Self::NonUniqueOrderLabel => "non_unique_order_label",
417            Self::NoMoreSecurityKeysAllowed => "no_more_security_keys_allowed",
418            Self::ActiveComboLimitReached => "active_combo_limit_reached",
419            Self::UnavailableForComboBooks => "unavailable_for_combo_books",
420            Self::IncompleteKycData => "incomplete_KYC_data",
421            Self::MmpRequired => "mmp_required",
422            Self::CodNotEnabled => "cod_not_enabled",
423            Self::QuotesFrozen => "quotes_frozen",
424            Self::ScopeExceeded => "scope_exceeded",
425            Self::Unavailable => "unavailable",
426            Self::RequestCancelledByUser => "request_cancelled_by_user",
427            Self::Replaced => "replaced",
428            Self::RawSubscriptionsNotAvailableForUnauthorized => {
429                "raw_subscriptions_not_available_for_unauthorized"
430            }
431            Self::MovePositionsOverLimit => "move_positions_over_limit",
432            Self::CouponAlreadyUsed => "coupon_already_used",
433            Self::KycTransferAlreadyInitiated => "KYC_transfer_already_initiated",
434            Self::Unknown(_) => "unknown_error",
435        }
436    }
437
438    /// Check if this is a success code
439    pub fn is_success(&self) -> bool {
440        matches!(self, Self::Success)
441    }
442
443    /// Check if this is an authorization error
444    pub fn is_authorization_error(&self) -> bool {
445        matches!(self, Self::AuthorizationRequired | Self::Unauthorized)
446    }
447
448    /// Check if this is a rate limiting error
449    pub fn is_rate_limit_error(&self) -> bool {
450        matches!(
451            self,
452            Self::TooManyRequests | Self::TooManyConcurrentRequests
453        )
454    }
455
456    /// Check if this is a validation error
457    pub fn is_validation_error(&self) -> bool {
458        matches!(
459            self,
460            Self::InvalidAmount
461                | Self::InvalidPrice
462                | Self::InvalidQuantity
463                | Self::InvalidOrderId
464                | Self::InvalidArguments
465                | Self::BadArgument
466                | Self::BadArguments
467                | Self::InvalidInput
468        )
469    }
470
471    /// Check if this is a trading error
472    pub fn is_trading_error(&self) -> bool {
473        matches!(
474            self,
475            Self::QtyTooLow
476                | Self::OrderOverlap
477                | Self::OrderNotFound
478                | Self::PriceTooLow
479                | Self::PriceTooHigh
480                | Self::NotEnoughFunds
481                | Self::AlreadyClosed
482                | Self::PriceNotAllowed
483                | Self::BookClosed
484        )
485    }
486}
487
488// Error trait implementation
489impl std::error::Error for DeribitErrorCode {}
490
491// Conversion from DeribitErrorCode to i32 (required for serde)
492impl From<DeribitErrorCode> for i32 {
493    fn from(error: DeribitErrorCode) -> Self {
494        match error {
495            DeribitErrorCode::Success => 0,
496            DeribitErrorCode::AuthorizationRequired => 10000,
497            DeribitErrorCode::Error => 10001,
498            DeribitErrorCode::QtyTooLow => 10002,
499            DeribitErrorCode::OrderOverlap => 10003,
500            DeribitErrorCode::OrderNotFound => 10004,
501            DeribitErrorCode::PriceTooLow => 10005,
502            DeribitErrorCode::PriceTooLow4Idx => 10006,
503            DeribitErrorCode::PriceTooHigh => 10007,
504            DeribitErrorCode::NotEnoughFunds => 10009,
505            DeribitErrorCode::AlreadyClosed => 10010,
506            DeribitErrorCode::PriceNotAllowed => 10011,
507            DeribitErrorCode::BookClosed => 10012,
508            DeribitErrorCode::PmeMaxTotalOpenOrders => 10013,
509            DeribitErrorCode::PmeMaxFutureOpenOrders => 10014,
510            DeribitErrorCode::PmeMaxOptionOpenOrders => 10015,
511            DeribitErrorCode::PmeMaxFutureOpenOrdersSize => 10016,
512            DeribitErrorCode::PmeMaxOptionOpenOrdersSize => 10017,
513            DeribitErrorCode::NonPmeMaxFuturePositionSize => 10018,
514            DeribitErrorCode::LockedByAdmin => 10019,
515            DeribitErrorCode::InvalidOrUnsupportedInstrument => 10020,
516            DeribitErrorCode::InvalidAmount => 10021,
517            DeribitErrorCode::InvalidQuantity => 10022,
518            DeribitErrorCode::InvalidPrice => 10023,
519            DeribitErrorCode::InvalidMaxShow => 10024,
520            DeribitErrorCode::InvalidOrderId => 10025,
521            DeribitErrorCode::PricePrecisionExceeded => 10026,
522            DeribitErrorCode::NonIntegerContractAmount => 10027,
523            DeribitErrorCode::TooManyRequests => 10028,
524            DeribitErrorCode::NotOwnerOfOrder => 10029,
525            DeribitErrorCode::MustBeWebsocketRequest => 10030,
526            DeribitErrorCode::InvalidArgsForInstrument => 10031,
527            DeribitErrorCode::WholeCostTooLow => 10032,
528            DeribitErrorCode::NotImplemented => 10033,
529            DeribitErrorCode::TriggerPriceTooHigh => 10034,
530            DeribitErrorCode::TriggerPriceTooLow => 10035,
531            DeribitErrorCode::InvalidMaxShowAmount => 10036,
532            DeribitErrorCode::NonPmeTotalShortOptionsPositionsSize => 10037,
533            DeribitErrorCode::PmeMaxRiskReducingOrders => 10038,
534            DeribitErrorCode::NotEnoughFundsInCurrency => 10039,
535            DeribitErrorCode::Retry => 10040,
536            DeribitErrorCode::SettlementInProgress => 10041,
537            DeribitErrorCode::PriceWrongTick => 10043,
538            DeribitErrorCode::TriggerPriceWrongTick => 10044,
539            DeribitErrorCode::CanNotCancelLiquidationOrder => 10045,
540            DeribitErrorCode::CanNotEditLiquidationOrder => 10046,
541            DeribitErrorCode::MatchingEngineQueueFull => 10047,
542            DeribitErrorCode::NotOnThisServer => 10048,
543            DeribitErrorCode::CancelOnDisconnectFailed => 10049,
544            DeribitErrorCode::TooManyConcurrentRequests => 10066,
545            DeribitErrorCode::DisabledWhilePositionLock => 10072,
546            DeribitErrorCode::AlreadyFilled => 11008,
547            DeribitErrorCode::MaxSpotOpenOrders => 11013,
548            DeribitErrorCode::PostOnlyPriceModificationNotPossible => 11021,
549            DeribitErrorCode::MaxSpotOrderQuantity => 11022,
550            DeribitErrorCode::InvalidArguments => 11029,
551            DeribitErrorCode::OtherReject => 11030,
552            DeribitErrorCode::OtherError => 11031,
553            DeribitErrorCode::NoMoreTriggers => 11035,
554            DeribitErrorCode::InvalidTriggerPrice => 11036,
555            DeribitErrorCode::OutdatedInstrumentForIvOrder => 11037,
556            DeribitErrorCode::NoAdvForFutures => 11038,
557            DeribitErrorCode::NoAdvPostonly => 11039,
558            DeribitErrorCode::NotAdvOrder => 11041,
559            DeribitErrorCode::PermissionDenied => 11042,
560            DeribitErrorCode::BadArgument => 11043,
561            DeribitErrorCode::NotOpenOrder => 11044,
562            DeribitErrorCode::InvalidEvent => 11045,
563            DeribitErrorCode::OutdatedInstrument => 11046,
564            DeribitErrorCode::UnsupportedArgCombination => 11047,
565            DeribitErrorCode::WrongMaxShowForOption => 11048,
566            DeribitErrorCode::BadArguments => 11049,
567            DeribitErrorCode::BadRequest => 11050,
568            DeribitErrorCode::SystemMaintenance => 11051,
569            DeribitErrorCode::SubscribeErrorUnsubscribed => 11052,
570            DeribitErrorCode::TransferNotFound => 11053,
571            DeribitErrorCode::PostOnlyReject => 11054,
572            DeribitErrorCode::PostOnlyNotAllowed => 11055,
573            DeribitErrorCode::UnauthenticatedPublicRequestsTemporarilyDisabled => 11056,
574            DeribitErrorCode::InvalidAddr => 11090,
575            DeribitErrorCode::InvalidTransferAddress => 11091,
576            DeribitErrorCode::AddressAlreadyExist => 11092,
577            DeribitErrorCode::MaxAddrCountExceeded => 11093,
578            DeribitErrorCode::InternalServerError => 11094,
579            DeribitErrorCode::DisabledDepositAddressCreation => 11095,
580            DeribitErrorCode::AddressBelongsToUser => 11096,
581            DeribitErrorCode::NoDepositAddress => 11097,
582            DeribitErrorCode::AccountLocked => 11098,
583            DeribitErrorCode::TooManySubaccounts => 12001,
584            DeribitErrorCode::WrongSubaccountName => 12002,
585            DeribitErrorCode::LoginOverLimit => 12003,
586            DeribitErrorCode::RegistrationOverLimit => 12004,
587            DeribitErrorCode::CountryIsBanned => 12005,
588            DeribitErrorCode::TransferNotAllowed => 12100,
589            DeribitErrorCode::SecurityKeyAuthorizationOverLimit => 12998,
590            DeribitErrorCode::InvalidCredentials => 13004,
591            DeribitErrorCode::PwdMatchError => 13005,
592            DeribitErrorCode::SecurityError => 13006,
593            DeribitErrorCode::UserNotFound => 13007,
594            DeribitErrorCode::RequestFailed => 13008,
595            DeribitErrorCode::Unauthorized => 13009,
596            DeribitErrorCode::ValueRequired => 13010,
597            DeribitErrorCode::ValueTooShort => 13011,
598            DeribitErrorCode::UnavailableInSubaccount => 13012,
599            DeribitErrorCode::InvalidPhoneNumber => 13013,
600            DeribitErrorCode::CannotSendSms => 13014,
601            DeribitErrorCode::InvalidSmsCode => 13015,
602            DeribitErrorCode::InvalidInput => 13016,
603            DeribitErrorCode::InvalidContentType => 13018,
604            DeribitErrorCode::OrderbookClosed => 13019,
605            DeribitErrorCode::NotFound => 13020,
606            DeribitErrorCode::Forbidden => 13021,
607            DeribitErrorCode::MethodSwitchedOffByAdmin => 13025,
608            DeribitErrorCode::TemporarilyUnavailable => 13028,
609            DeribitErrorCode::MmpTrigger => 13030,
610            DeribitErrorCode::VerificationRequired => 13031,
611            DeribitErrorCode::NonUniqueOrderLabel => 13032,
612            DeribitErrorCode::NoMoreSecurityKeysAllowed => 13034,
613            DeribitErrorCode::ActiveComboLimitReached => 13035,
614            DeribitErrorCode::UnavailableForComboBooks => 13036,
615            DeribitErrorCode::IncompleteKycData => 13037,
616            DeribitErrorCode::MmpRequired => 13040,
617            DeribitErrorCode::CodNotEnabled => 13042,
618            DeribitErrorCode::QuotesFrozen => 13043,
619            DeribitErrorCode::ScopeExceeded => 13403,
620            DeribitErrorCode::Unavailable => 13503,
621            DeribitErrorCode::RequestCancelledByUser => 13666,
622            DeribitErrorCode::Replaced => 13777,
623            DeribitErrorCode::RawSubscriptionsNotAvailableForUnauthorized => 13778,
624            DeribitErrorCode::MovePositionsOverLimit => 13780,
625            DeribitErrorCode::CouponAlreadyUsed => 13781,
626            DeribitErrorCode::KycTransferAlreadyInitiated => 13791,
627            DeribitErrorCode::Unknown(code) => code,
628        }
629    }
630}
631
632// Conversion from i32 to DeribitErrorCode (required for serde)
633impl From<i32> for DeribitErrorCode {
634    fn from(code: i32) -> Self {
635        match code {
636            0 => DeribitErrorCode::Success,
637            10000 => DeribitErrorCode::AuthorizationRequired,
638            10001 => DeribitErrorCode::Error,
639            10002 => DeribitErrorCode::QtyTooLow,
640            10003 => DeribitErrorCode::OrderOverlap,
641            10004 => DeribitErrorCode::OrderNotFound,
642            10005 => DeribitErrorCode::PriceTooLow,
643            10006 => DeribitErrorCode::PriceTooLow4Idx,
644            10007 => DeribitErrorCode::PriceTooHigh,
645            10009 => DeribitErrorCode::NotEnoughFunds,
646            10010 => DeribitErrorCode::AlreadyClosed,
647            10011 => DeribitErrorCode::PriceNotAllowed,
648            10012 => DeribitErrorCode::BookClosed,
649            10013 => DeribitErrorCode::PmeMaxTotalOpenOrders,
650            10014 => DeribitErrorCode::PmeMaxFutureOpenOrders,
651            10015 => DeribitErrorCode::PmeMaxOptionOpenOrders,
652            10016 => DeribitErrorCode::PmeMaxFutureOpenOrdersSize,
653            10017 => DeribitErrorCode::PmeMaxOptionOpenOrdersSize,
654            10018 => DeribitErrorCode::NonPmeMaxFuturePositionSize,
655            10019 => DeribitErrorCode::LockedByAdmin,
656            10020 => DeribitErrorCode::InvalidOrUnsupportedInstrument,
657            10021 => DeribitErrorCode::InvalidAmount,
658            10022 => DeribitErrorCode::InvalidQuantity,
659            10023 => DeribitErrorCode::InvalidPrice,
660            10024 => DeribitErrorCode::InvalidMaxShow,
661            10025 => DeribitErrorCode::InvalidOrderId,
662            10026 => DeribitErrorCode::PricePrecisionExceeded,
663            10027 => DeribitErrorCode::NonIntegerContractAmount,
664            10028 => DeribitErrorCode::TooManyRequests,
665            10029 => DeribitErrorCode::NotOwnerOfOrder,
666            10030 => DeribitErrorCode::MustBeWebsocketRequest,
667            10031 => DeribitErrorCode::InvalidArgsForInstrument,
668            10032 => DeribitErrorCode::WholeCostTooLow,
669            10033 => DeribitErrorCode::NotImplemented,
670            10034 => DeribitErrorCode::TriggerPriceTooHigh,
671            10035 => DeribitErrorCode::TriggerPriceTooLow,
672            10036 => DeribitErrorCode::InvalidMaxShowAmount,
673            10037 => DeribitErrorCode::NonPmeTotalShortOptionsPositionsSize,
674            10038 => DeribitErrorCode::PmeMaxRiskReducingOrders,
675            10039 => DeribitErrorCode::NotEnoughFundsInCurrency,
676            10040 => DeribitErrorCode::Retry,
677            10041 => DeribitErrorCode::SettlementInProgress,
678            10043 => DeribitErrorCode::PriceWrongTick,
679            10044 => DeribitErrorCode::TriggerPriceWrongTick,
680            10045 => DeribitErrorCode::CanNotCancelLiquidationOrder,
681            10046 => DeribitErrorCode::CanNotEditLiquidationOrder,
682            10047 => DeribitErrorCode::MatchingEngineQueueFull,
683            10048 => DeribitErrorCode::NotOnThisServer,
684            10049 => DeribitErrorCode::CancelOnDisconnectFailed,
685            10066 => DeribitErrorCode::TooManyConcurrentRequests,
686            10072 => DeribitErrorCode::DisabledWhilePositionLock,
687            11008 => DeribitErrorCode::AlreadyFilled,
688            11013 => DeribitErrorCode::MaxSpotOpenOrders,
689            11021 => DeribitErrorCode::PostOnlyPriceModificationNotPossible,
690            11022 => DeribitErrorCode::MaxSpotOrderQuantity,
691            11029 => DeribitErrorCode::InvalidArguments,
692            11030 => DeribitErrorCode::OtherReject,
693            11031 => DeribitErrorCode::OtherError,
694            11035 => DeribitErrorCode::NoMoreTriggers,
695            11036 => DeribitErrorCode::InvalidTriggerPrice,
696            11037 => DeribitErrorCode::OutdatedInstrumentForIvOrder,
697            11038 => DeribitErrorCode::NoAdvForFutures,
698            11039 => DeribitErrorCode::NoAdvPostonly,
699            11041 => DeribitErrorCode::NotAdvOrder,
700            11042 => DeribitErrorCode::PermissionDenied,
701            11043 => DeribitErrorCode::BadArgument,
702            11044 => DeribitErrorCode::NotOpenOrder,
703            11045 => DeribitErrorCode::InvalidEvent,
704            11046 => DeribitErrorCode::OutdatedInstrument,
705            11047 => DeribitErrorCode::UnsupportedArgCombination,
706            11048 => DeribitErrorCode::WrongMaxShowForOption,
707            11049 => DeribitErrorCode::BadArguments,
708            11050 => DeribitErrorCode::BadRequest,
709            11051 => DeribitErrorCode::SystemMaintenance,
710            11052 => DeribitErrorCode::SubscribeErrorUnsubscribed,
711            11053 => DeribitErrorCode::TransferNotFound,
712            11054 => DeribitErrorCode::PostOnlyReject,
713            11055 => DeribitErrorCode::PostOnlyNotAllowed,
714            11056 => DeribitErrorCode::UnauthenticatedPublicRequestsTemporarilyDisabled,
715            11090 => DeribitErrorCode::InvalidAddr,
716            11091 => DeribitErrorCode::InvalidTransferAddress,
717            11092 => DeribitErrorCode::AddressAlreadyExist,
718            11093 => DeribitErrorCode::MaxAddrCountExceeded,
719            11094 => DeribitErrorCode::InternalServerError,
720            11095 => DeribitErrorCode::DisabledDepositAddressCreation,
721            11096 => DeribitErrorCode::AddressBelongsToUser,
722            11097 => DeribitErrorCode::NoDepositAddress,
723            11098 => DeribitErrorCode::AccountLocked,
724            12001 => DeribitErrorCode::TooManySubaccounts,
725            12002 => DeribitErrorCode::WrongSubaccountName,
726            12003 => DeribitErrorCode::LoginOverLimit,
727            12004 => DeribitErrorCode::RegistrationOverLimit,
728            12005 => DeribitErrorCode::CountryIsBanned,
729            12100 => DeribitErrorCode::TransferNotAllowed,
730            12998 => DeribitErrorCode::SecurityKeyAuthorizationOverLimit,
731            13004 => DeribitErrorCode::InvalidCredentials,
732            13005 => DeribitErrorCode::PwdMatchError,
733            13006 => DeribitErrorCode::SecurityError,
734            13007 => DeribitErrorCode::UserNotFound,
735            13008 => DeribitErrorCode::RequestFailed,
736            13009 => DeribitErrorCode::Unauthorized,
737            13010 => DeribitErrorCode::ValueRequired,
738            13011 => DeribitErrorCode::ValueTooShort,
739            13012 => DeribitErrorCode::UnavailableInSubaccount,
740            13013 => DeribitErrorCode::InvalidPhoneNumber,
741            13014 => DeribitErrorCode::CannotSendSms,
742            13015 => DeribitErrorCode::InvalidSmsCode,
743            13016 => DeribitErrorCode::InvalidInput,
744            13018 => DeribitErrorCode::InvalidContentType,
745            13019 => DeribitErrorCode::OrderbookClosed,
746            13020 => DeribitErrorCode::NotFound,
747            13021 => DeribitErrorCode::Forbidden,
748            13025 => DeribitErrorCode::MethodSwitchedOffByAdmin,
749            13028 => DeribitErrorCode::TemporarilyUnavailable,
750            13030 => DeribitErrorCode::MmpTrigger,
751            13031 => DeribitErrorCode::VerificationRequired,
752            13032 => DeribitErrorCode::NonUniqueOrderLabel,
753            13034 => DeribitErrorCode::NoMoreSecurityKeysAllowed,
754            13035 => DeribitErrorCode::ActiveComboLimitReached,
755            13036 => DeribitErrorCode::UnavailableForComboBooks,
756            13037 => DeribitErrorCode::IncompleteKycData,
757            13040 => DeribitErrorCode::MmpRequired,
758            13042 => DeribitErrorCode::CodNotEnabled,
759            13043 => DeribitErrorCode::QuotesFrozen,
760            13403 => DeribitErrorCode::ScopeExceeded,
761            13503 => DeribitErrorCode::Unavailable,
762            13666 => DeribitErrorCode::RequestCancelledByUser,
763            13777 => DeribitErrorCode::Replaced,
764            13778 => DeribitErrorCode::RawSubscriptionsNotAvailableForUnauthorized,
765            13780 => DeribitErrorCode::MovePositionsOverLimit,
766            13781 => DeribitErrorCode::CouponAlreadyUsed,
767            13791 => DeribitErrorCode::KycTransferAlreadyInitiated,
768            _ => DeribitErrorCode::Unknown(code),
769        }
770    }
771}
772
773#[cfg(test)]
774mod tests {
775    use super::*;
776
777    #[test]
778    fn test_error_code_conversion() {
779        let error = DeribitErrorCode::from(10000);
780        assert_eq!(error, DeribitErrorCode::AuthorizationRequired);
781        assert_eq!(error.code(), 10000);
782        assert_eq!(error.message(), "authorization_required");
783    }
784
785    #[test]
786    fn test_unknown_error_code() {
787        let error = DeribitErrorCode::from(99999);
788        assert_eq!(error, DeribitErrorCode::Unknown(99999));
789        assert_eq!(error.code(), 99999);
790        assert_eq!(error.message(), "unknown_error");
791    }
792
793    #[test]
794    fn test_success_code() {
795        let error = DeribitErrorCode::from(0);
796        assert_eq!(error, DeribitErrorCode::Success);
797        assert!(error.is_success());
798        assert!(!error.is_authorization_error());
799    }
800
801    #[test]
802    fn test_error_categorization() {
803        let auth_error = DeribitErrorCode::AuthorizationRequired;
804        assert!(auth_error.is_authorization_error());
805        assert!(!auth_error.is_trading_error());
806
807        let trading_error = DeribitErrorCode::QtyTooLow;
808        assert!(trading_error.is_trading_error());
809        assert!(!trading_error.is_authorization_error());
810
811        let rate_limit_error = DeribitErrorCode::TooManyRequests;
812        assert!(rate_limit_error.is_rate_limit_error());
813        assert!(!rate_limit_error.is_validation_error());
814
815        let validation_error = DeribitErrorCode::InvalidAmount;
816        assert!(validation_error.is_validation_error());
817        assert!(!validation_error.is_rate_limit_error());
818    }
819
820    #[test]
821    fn test_serde_serialization() {
822        let error = DeribitErrorCode::AuthorizationRequired;
823        let json = serde_json::to_string(&error).unwrap();
824        assert_eq!(json, "10000");
825
826        let deserialized: DeribitErrorCode = serde_json::from_str(&json).unwrap();
827        assert_eq!(deserialized, error);
828    }
829
830    #[test]
831    fn test_specific_error_codes() {
832        // Test some key error codes to ensure they map correctly
833        assert_eq!(DeribitErrorCode::from(0), DeribitErrorCode::Success);
834        assert_eq!(DeribitErrorCode::from(10001), DeribitErrorCode::Error);
835        assert_eq!(DeribitErrorCode::from(10002), DeribitErrorCode::QtyTooLow);
836        assert_eq!(
837            DeribitErrorCode::from(13009),
838            DeribitErrorCode::Unauthorized
839        );
840        assert_eq!(DeribitErrorCode::from(13020), DeribitErrorCode::NotFound);
841
842        // Test reverse conversion
843        assert_eq!(DeribitErrorCode::Success.code(), 0);
844        assert_eq!(DeribitErrorCode::AuthorizationRequired.code(), 10000);
845        assert_eq!(DeribitErrorCode::TooManyRequests.code(), 10028);
846    }
847
848    #[test]
849    fn test_all_error_code_conversions() {
850        // Test all error codes for bidirectional conversion
851        let test_cases = vec![
852            (0, DeribitErrorCode::Success),
853            (10000, DeribitErrorCode::AuthorizationRequired),
854            (10001, DeribitErrorCode::Error),
855            (10002, DeribitErrorCode::QtyTooLow),
856            (10003, DeribitErrorCode::OrderOverlap),
857            (10004, DeribitErrorCode::OrderNotFound),
858            (10005, DeribitErrorCode::PriceTooLow),
859            (10006, DeribitErrorCode::PriceTooLow4Idx),
860            (10007, DeribitErrorCode::PriceTooHigh),
861            (10009, DeribitErrorCode::NotEnoughFunds),
862            (10010, DeribitErrorCode::AlreadyClosed),
863            (10011, DeribitErrorCode::PriceNotAllowed),
864            (10012, DeribitErrorCode::BookClosed),
865            (10013, DeribitErrorCode::PmeMaxTotalOpenOrders),
866            (10014, DeribitErrorCode::PmeMaxFutureOpenOrders),
867            (10015, DeribitErrorCode::PmeMaxOptionOpenOrders),
868            (10016, DeribitErrorCode::PmeMaxFutureOpenOrdersSize),
869            (10017, DeribitErrorCode::PmeMaxOptionOpenOrdersSize),
870            (10018, DeribitErrorCode::NonPmeMaxFuturePositionSize),
871            (10019, DeribitErrorCode::LockedByAdmin),
872            (10020, DeribitErrorCode::InvalidOrUnsupportedInstrument),
873            (10021, DeribitErrorCode::InvalidAmount),
874            (10022, DeribitErrorCode::InvalidQuantity),
875            (10023, DeribitErrorCode::InvalidPrice),
876            (10024, DeribitErrorCode::InvalidMaxShow),
877            (10025, DeribitErrorCode::InvalidOrderId),
878            (10026, DeribitErrorCode::PricePrecisionExceeded),
879            (10027, DeribitErrorCode::NonIntegerContractAmount),
880            (10028, DeribitErrorCode::TooManyRequests),
881            (10029, DeribitErrorCode::NotOwnerOfOrder),
882            (10030, DeribitErrorCode::MustBeWebsocketRequest),
883            (10031, DeribitErrorCode::InvalidArgsForInstrument),
884            (10032, DeribitErrorCode::WholeCostTooLow),
885            (10033, DeribitErrorCode::NotImplemented),
886            (10034, DeribitErrorCode::TriggerPriceTooHigh),
887            (10035, DeribitErrorCode::TriggerPriceTooLow),
888            (10036, DeribitErrorCode::InvalidMaxShowAmount),
889            (
890                10037,
891                DeribitErrorCode::NonPmeTotalShortOptionsPositionsSize,
892            ),
893            (10038, DeribitErrorCode::PmeMaxRiskReducingOrders),
894            (10039, DeribitErrorCode::NotEnoughFundsInCurrency),
895            (10040, DeribitErrorCode::Retry),
896            (10041, DeribitErrorCode::SettlementInProgress),
897            (10043, DeribitErrorCode::PriceWrongTick),
898            (10044, DeribitErrorCode::TriggerPriceWrongTick),
899            (10045, DeribitErrorCode::CanNotCancelLiquidationOrder),
900            (10046, DeribitErrorCode::CanNotEditLiquidationOrder),
901            (10047, DeribitErrorCode::MatchingEngineQueueFull),
902            (10048, DeribitErrorCode::NotOnThisServer),
903            (10049, DeribitErrorCode::CancelOnDisconnectFailed),
904            (10066, DeribitErrorCode::TooManyConcurrentRequests),
905            (10072, DeribitErrorCode::DisabledWhilePositionLock),
906            (11008, DeribitErrorCode::AlreadyFilled),
907            (11013, DeribitErrorCode::MaxSpotOpenOrders),
908            (
909                11021,
910                DeribitErrorCode::PostOnlyPriceModificationNotPossible,
911            ),
912            (11022, DeribitErrorCode::MaxSpotOrderQuantity),
913            (11029, DeribitErrorCode::InvalidArguments),
914            (11030, DeribitErrorCode::OtherReject),
915            (11031, DeribitErrorCode::OtherError),
916            (11035, DeribitErrorCode::NoMoreTriggers),
917            (11036, DeribitErrorCode::InvalidTriggerPrice),
918            (11037, DeribitErrorCode::OutdatedInstrumentForIvOrder),
919            (11038, DeribitErrorCode::NoAdvForFutures),
920            (11039, DeribitErrorCode::NoAdvPostonly),
921            (11041, DeribitErrorCode::NotAdvOrder),
922            (11042, DeribitErrorCode::PermissionDenied),
923            (11043, DeribitErrorCode::BadArgument),
924            (11044, DeribitErrorCode::NotOpenOrder),
925            (11045, DeribitErrorCode::InvalidEvent),
926            (11046, DeribitErrorCode::OutdatedInstrument),
927            (11047, DeribitErrorCode::UnsupportedArgCombination),
928            (11048, DeribitErrorCode::WrongMaxShowForOption),
929            (11049, DeribitErrorCode::BadArguments),
930            (11050, DeribitErrorCode::BadRequest),
931            (11051, DeribitErrorCode::SystemMaintenance),
932            (11052, DeribitErrorCode::SubscribeErrorUnsubscribed),
933            (11053, DeribitErrorCode::TransferNotFound),
934            (11054, DeribitErrorCode::PostOnlyReject),
935            (11055, DeribitErrorCode::PostOnlyNotAllowed),
936            (
937                11056,
938                DeribitErrorCode::UnauthenticatedPublicRequestsTemporarilyDisabled,
939            ),
940            (11090, DeribitErrorCode::InvalidAddr),
941            (11091, DeribitErrorCode::InvalidTransferAddress),
942            (11092, DeribitErrorCode::AddressAlreadyExist),
943            (11093, DeribitErrorCode::MaxAddrCountExceeded),
944            (11094, DeribitErrorCode::InternalServerError),
945            (11095, DeribitErrorCode::DisabledDepositAddressCreation),
946            (11096, DeribitErrorCode::AddressBelongsToUser),
947            (11097, DeribitErrorCode::NoDepositAddress),
948            (11098, DeribitErrorCode::AccountLocked),
949            (12001, DeribitErrorCode::TooManySubaccounts),
950            (12002, DeribitErrorCode::WrongSubaccountName),
951            (12003, DeribitErrorCode::LoginOverLimit),
952            (12004, DeribitErrorCode::RegistrationOverLimit),
953            (12005, DeribitErrorCode::CountryIsBanned),
954            (12100, DeribitErrorCode::TransferNotAllowed),
955            (12998, DeribitErrorCode::SecurityKeyAuthorizationOverLimit),
956            (13004, DeribitErrorCode::InvalidCredentials),
957            (13005, DeribitErrorCode::PwdMatchError),
958            (13006, DeribitErrorCode::SecurityError),
959            (13007, DeribitErrorCode::UserNotFound),
960            (13008, DeribitErrorCode::RequestFailed),
961            (13009, DeribitErrorCode::Unauthorized),
962            (13010, DeribitErrorCode::ValueRequired),
963            (13011, DeribitErrorCode::ValueTooShort),
964            (13012, DeribitErrorCode::UnavailableInSubaccount),
965            (13013, DeribitErrorCode::InvalidPhoneNumber),
966            (13014, DeribitErrorCode::CannotSendSms),
967            (13015, DeribitErrorCode::InvalidSmsCode),
968            (13016, DeribitErrorCode::InvalidInput),
969            (13018, DeribitErrorCode::InvalidContentType),
970            (13019, DeribitErrorCode::OrderbookClosed),
971            (13020, DeribitErrorCode::NotFound),
972            (13021, DeribitErrorCode::Forbidden),
973            (13025, DeribitErrorCode::MethodSwitchedOffByAdmin),
974            (13028, DeribitErrorCode::TemporarilyUnavailable),
975            (13030, DeribitErrorCode::MmpTrigger),
976            (13031, DeribitErrorCode::VerificationRequired),
977            (13032, DeribitErrorCode::NonUniqueOrderLabel),
978            (13034, DeribitErrorCode::NoMoreSecurityKeysAllowed),
979            (13035, DeribitErrorCode::ActiveComboLimitReached),
980            (13036, DeribitErrorCode::UnavailableForComboBooks),
981            (13037, DeribitErrorCode::IncompleteKycData),
982            (13040, DeribitErrorCode::MmpRequired),
983            (13042, DeribitErrorCode::CodNotEnabled),
984            (13043, DeribitErrorCode::QuotesFrozen),
985            (13403, DeribitErrorCode::ScopeExceeded),
986            (13503, DeribitErrorCode::Unavailable),
987            (13666, DeribitErrorCode::RequestCancelledByUser),
988            (13777, DeribitErrorCode::Replaced),
989            (
990                13778,
991                DeribitErrorCode::RawSubscriptionsNotAvailableForUnauthorized,
992            ),
993            (13780, DeribitErrorCode::MovePositionsOverLimit),
994            (13781, DeribitErrorCode::CouponAlreadyUsed),
995            (13791, DeribitErrorCode::KycTransferAlreadyInitiated),
996        ];
997
998        for (code, expected_error) in test_cases {
999            // Test conversion from i32 to DeribitErrorCode
1000            let error = DeribitErrorCode::from(code);
1001            assert_eq!(error, expected_error, "Failed for code {}", code);
1002
1003            // Test conversion from DeribitErrorCode to i32
1004            assert_eq!(
1005                error.code(),
1006                code,
1007                "Failed reverse conversion for {:?}",
1008                expected_error
1009            );
1010        }
1011    }
1012
1013    #[test]
1014    fn test_all_error_messages() {
1015        // Test that all error codes have proper messages
1016        let error_codes = vec![
1017            DeribitErrorCode::Success,
1018            DeribitErrorCode::AuthorizationRequired,
1019            DeribitErrorCode::Error,
1020            DeribitErrorCode::QtyTooLow,
1021            DeribitErrorCode::OrderOverlap,
1022            DeribitErrorCode::OrderNotFound,
1023            DeribitErrorCode::PriceTooLow,
1024            DeribitErrorCode::PriceTooLow4Idx,
1025            DeribitErrorCode::PriceTooHigh,
1026            DeribitErrorCode::NotEnoughFunds,
1027            DeribitErrorCode::AlreadyClosed,
1028            DeribitErrorCode::PriceNotAllowed,
1029            DeribitErrorCode::BookClosed,
1030            DeribitErrorCode::PmeMaxTotalOpenOrders,
1031            DeribitErrorCode::PmeMaxFutureOpenOrders,
1032            DeribitErrorCode::PmeMaxOptionOpenOrders,
1033            DeribitErrorCode::PmeMaxFutureOpenOrdersSize,
1034            DeribitErrorCode::PmeMaxOptionOpenOrdersSize,
1035            DeribitErrorCode::NonPmeMaxFuturePositionSize,
1036            DeribitErrorCode::LockedByAdmin,
1037            DeribitErrorCode::InvalidOrUnsupportedInstrument,
1038            DeribitErrorCode::InvalidAmount,
1039            DeribitErrorCode::InvalidQuantity,
1040            DeribitErrorCode::InvalidPrice,
1041            DeribitErrorCode::InvalidMaxShow,
1042            DeribitErrorCode::InvalidOrderId,
1043            DeribitErrorCode::PricePrecisionExceeded,
1044            DeribitErrorCode::NonIntegerContractAmount,
1045            DeribitErrorCode::TooManyRequests,
1046            DeribitErrorCode::NotOwnerOfOrder,
1047            DeribitErrorCode::MustBeWebsocketRequest,
1048            DeribitErrorCode::InvalidArgsForInstrument,
1049            DeribitErrorCode::WholeCostTooLow,
1050            DeribitErrorCode::NotImplemented,
1051            DeribitErrorCode::TriggerPriceTooHigh,
1052            DeribitErrorCode::TriggerPriceTooLow,
1053            DeribitErrorCode::InvalidMaxShowAmount,
1054            DeribitErrorCode::NonPmeTotalShortOptionsPositionsSize,
1055            DeribitErrorCode::PmeMaxRiskReducingOrders,
1056            DeribitErrorCode::NotEnoughFundsInCurrency,
1057            DeribitErrorCode::Retry,
1058            DeribitErrorCode::SettlementInProgress,
1059            DeribitErrorCode::PriceWrongTick,
1060            DeribitErrorCode::TriggerPriceWrongTick,
1061            DeribitErrorCode::CanNotCancelLiquidationOrder,
1062            DeribitErrorCode::CanNotEditLiquidationOrder,
1063            DeribitErrorCode::MatchingEngineQueueFull,
1064            DeribitErrorCode::NotOnThisServer,
1065            DeribitErrorCode::CancelOnDisconnectFailed,
1066            DeribitErrorCode::TooManyConcurrentRequests,
1067            DeribitErrorCode::DisabledWhilePositionLock,
1068            DeribitErrorCode::AlreadyFilled,
1069            DeribitErrorCode::MaxSpotOpenOrders,
1070            DeribitErrorCode::PostOnlyPriceModificationNotPossible,
1071            DeribitErrorCode::MaxSpotOrderQuantity,
1072            DeribitErrorCode::InvalidArguments,
1073            DeribitErrorCode::OtherReject,
1074            DeribitErrorCode::OtherError,
1075            DeribitErrorCode::NoMoreTriggers,
1076            DeribitErrorCode::InvalidTriggerPrice,
1077            DeribitErrorCode::OutdatedInstrumentForIvOrder,
1078            DeribitErrorCode::NoAdvForFutures,
1079            DeribitErrorCode::NoAdvPostonly,
1080            DeribitErrorCode::NotAdvOrder,
1081            DeribitErrorCode::PermissionDenied,
1082            DeribitErrorCode::BadArgument,
1083            DeribitErrorCode::NotOpenOrder,
1084            DeribitErrorCode::InvalidEvent,
1085            DeribitErrorCode::OutdatedInstrument,
1086            DeribitErrorCode::UnsupportedArgCombination,
1087            DeribitErrorCode::WrongMaxShowForOption,
1088            DeribitErrorCode::BadArguments,
1089            DeribitErrorCode::BadRequest,
1090            DeribitErrorCode::SystemMaintenance,
1091            DeribitErrorCode::SubscribeErrorUnsubscribed,
1092            DeribitErrorCode::TransferNotFound,
1093            DeribitErrorCode::PostOnlyReject,
1094            DeribitErrorCode::PostOnlyNotAllowed,
1095            DeribitErrorCode::UnauthenticatedPublicRequestsTemporarilyDisabled,
1096            DeribitErrorCode::InvalidAddr,
1097            DeribitErrorCode::InvalidTransferAddress,
1098            DeribitErrorCode::AddressAlreadyExist,
1099            DeribitErrorCode::MaxAddrCountExceeded,
1100            DeribitErrorCode::InternalServerError,
1101            DeribitErrorCode::DisabledDepositAddressCreation,
1102            DeribitErrorCode::AddressBelongsToUser,
1103            DeribitErrorCode::NoDepositAddress,
1104            DeribitErrorCode::AccountLocked,
1105            DeribitErrorCode::TooManySubaccounts,
1106            DeribitErrorCode::WrongSubaccountName,
1107            DeribitErrorCode::LoginOverLimit,
1108            DeribitErrorCode::RegistrationOverLimit,
1109            DeribitErrorCode::CountryIsBanned,
1110            DeribitErrorCode::TransferNotAllowed,
1111            DeribitErrorCode::SecurityKeyAuthorizationOverLimit,
1112            DeribitErrorCode::InvalidCredentials,
1113            DeribitErrorCode::PwdMatchError,
1114            DeribitErrorCode::SecurityError,
1115            DeribitErrorCode::UserNotFound,
1116            DeribitErrorCode::RequestFailed,
1117            DeribitErrorCode::Unauthorized,
1118            DeribitErrorCode::ValueRequired,
1119            DeribitErrorCode::ValueTooShort,
1120            DeribitErrorCode::UnavailableInSubaccount,
1121            DeribitErrorCode::InvalidPhoneNumber,
1122            DeribitErrorCode::CannotSendSms,
1123            DeribitErrorCode::InvalidSmsCode,
1124            DeribitErrorCode::InvalidInput,
1125            DeribitErrorCode::InvalidContentType,
1126            DeribitErrorCode::OrderbookClosed,
1127            DeribitErrorCode::NotFound,
1128            DeribitErrorCode::Forbidden,
1129            DeribitErrorCode::MethodSwitchedOffByAdmin,
1130            DeribitErrorCode::TemporarilyUnavailable,
1131            DeribitErrorCode::MmpTrigger,
1132            DeribitErrorCode::VerificationRequired,
1133            DeribitErrorCode::NonUniqueOrderLabel,
1134            DeribitErrorCode::NoMoreSecurityKeysAllowed,
1135            DeribitErrorCode::ActiveComboLimitReached,
1136            DeribitErrorCode::UnavailableForComboBooks,
1137            DeribitErrorCode::IncompleteKycData,
1138            DeribitErrorCode::MmpRequired,
1139            DeribitErrorCode::CodNotEnabled,
1140            DeribitErrorCode::QuotesFrozen,
1141            DeribitErrorCode::ScopeExceeded,
1142            DeribitErrorCode::Unavailable,
1143            DeribitErrorCode::RequestCancelledByUser,
1144            DeribitErrorCode::Replaced,
1145            DeribitErrorCode::RawSubscriptionsNotAvailableForUnauthorized,
1146            DeribitErrorCode::MovePositionsOverLimit,
1147            DeribitErrorCode::CouponAlreadyUsed,
1148            DeribitErrorCode::KycTransferAlreadyInitiated,
1149            DeribitErrorCode::Unknown(12345),
1150        ];
1151
1152        for error_code in error_codes {
1153            let message = error_code.message();
1154            assert!(
1155                !message.is_empty(),
1156                "Message should not be empty for {:?}",
1157                error_code
1158            );
1159            assert!(
1160                !message.is_empty(),
1161                "Message should have content for {:?}",
1162                error_code
1163            );
1164        }
1165    }
1166
1167    #[test]
1168    fn test_comprehensive_error_categorization() {
1169        // Test authorization errors
1170        let auth_errors = vec![
1171            DeribitErrorCode::AuthorizationRequired,
1172            DeribitErrorCode::Unauthorized,
1173        ];
1174        for error in auth_errors {
1175            assert!(
1176                error.is_authorization_error(),
1177                "{:?} should be authorization error",
1178                error
1179            );
1180            assert!(!error.is_success(), "{:?} should not be success", error);
1181            assert!(
1182                !error.is_rate_limit_error(),
1183                "{:?} should not be rate limit error",
1184                error
1185            );
1186            assert!(
1187                !error.is_validation_error(),
1188                "{:?} should not be validation error",
1189                error
1190            );
1191            assert!(
1192                !error.is_trading_error(),
1193                "{:?} should not be trading error",
1194                error
1195            );
1196        }
1197
1198        // Test rate limit errors
1199        let rate_limit_errors = vec![
1200            DeribitErrorCode::TooManyRequests,
1201            DeribitErrorCode::TooManyConcurrentRequests,
1202        ];
1203        for error in rate_limit_errors {
1204            assert!(
1205                error.is_rate_limit_error(),
1206                "{:?} should be rate limit error",
1207                error
1208            );
1209            assert!(!error.is_success(), "{:?} should not be success", error);
1210            assert!(
1211                !error.is_authorization_error(),
1212                "{:?} should not be authorization error",
1213                error
1214            );
1215            assert!(
1216                !error.is_validation_error(),
1217                "{:?} should not be validation error",
1218                error
1219            );
1220            assert!(
1221                !error.is_trading_error(),
1222                "{:?} should not be trading error",
1223                error
1224            );
1225        }
1226
1227        // Test validation errors
1228        let validation_errors = vec![
1229            DeribitErrorCode::InvalidAmount,
1230            DeribitErrorCode::InvalidPrice,
1231            DeribitErrorCode::InvalidQuantity,
1232            DeribitErrorCode::InvalidOrderId,
1233            DeribitErrorCode::InvalidArguments,
1234            DeribitErrorCode::BadArgument,
1235            DeribitErrorCode::BadArguments,
1236            DeribitErrorCode::InvalidInput,
1237        ];
1238        for error in validation_errors {
1239            assert!(
1240                error.is_validation_error(),
1241                "{:?} should be validation error",
1242                error
1243            );
1244            assert!(!error.is_success(), "{:?} should not be success", error);
1245            assert!(
1246                !error.is_authorization_error(),
1247                "{:?} should not be authorization error",
1248                error
1249            );
1250            assert!(
1251                !error.is_rate_limit_error(),
1252                "{:?} should not be rate limit error",
1253                error
1254            );
1255            assert!(
1256                !error.is_trading_error(),
1257                "{:?} should not be trading error",
1258                error
1259            );
1260        }
1261
1262        // Test trading errors
1263        let trading_errors = vec![
1264            DeribitErrorCode::QtyTooLow,
1265            DeribitErrorCode::OrderOverlap,
1266            DeribitErrorCode::OrderNotFound,
1267            DeribitErrorCode::PriceTooLow,
1268            DeribitErrorCode::PriceTooHigh,
1269            DeribitErrorCode::NotEnoughFunds,
1270            DeribitErrorCode::AlreadyClosed,
1271            DeribitErrorCode::PriceNotAllowed,
1272            DeribitErrorCode::BookClosed,
1273        ];
1274        for error in trading_errors {
1275            assert!(
1276                error.is_trading_error(),
1277                "{:?} should be trading error",
1278                error
1279            );
1280            assert!(!error.is_success(), "{:?} should not be success", error);
1281            assert!(
1282                !error.is_authorization_error(),
1283                "{:?} should not be authorization error",
1284                error
1285            );
1286            assert!(
1287                !error.is_rate_limit_error(),
1288                "{:?} should not be rate limit error",
1289                error
1290            );
1291            assert!(
1292                !error.is_validation_error(),
1293                "{:?} should not be validation error",
1294                error
1295            );
1296        }
1297
1298        // Test success
1299        let success = DeribitErrorCode::Success;
1300        assert!(success.is_success(), "Success should be success");
1301        assert!(
1302            !success.is_authorization_error(),
1303            "Success should not be authorization error"
1304        );
1305        assert!(
1306            !success.is_rate_limit_error(),
1307            "Success should not be rate limit error"
1308        );
1309        assert!(
1310            !success.is_validation_error(),
1311            "Success should not be validation error"
1312        );
1313        assert!(
1314            !success.is_trading_error(),
1315            "Success should not be trading error"
1316        );
1317    }
1318
1319    #[test]
1320    fn test_error_trait_implementation() {
1321        let error = DeribitErrorCode::AuthorizationRequired;
1322        let error_trait: &dyn std::error::Error = &error;
1323        assert!(error_trait.source().is_none());
1324    }
1325
1326    #[test]
1327    fn test_clone_and_equality() {
1328        let error1 = DeribitErrorCode::AuthorizationRequired;
1329        let error2 = error1.clone();
1330        assert_eq!(error1, error2);
1331
1332        let error3 = DeribitErrorCode::Error;
1333        assert_ne!(error1, error3);
1334
1335        let unknown1 = DeribitErrorCode::Unknown(12345);
1336        let unknown2 = DeribitErrorCode::Unknown(12345);
1337        let unknown3 = DeribitErrorCode::Unknown(54321);
1338        assert_eq!(unknown1, unknown2);
1339        assert_ne!(unknown1, unknown3);
1340    }
1341
1342    #[test]
1343    fn test_hash_implementation() {
1344        use std::collections::HashSet;
1345
1346        let mut error_set = HashSet::new();
1347        error_set.insert(DeribitErrorCode::AuthorizationRequired);
1348        error_set.insert(DeribitErrorCode::Error);
1349        error_set.insert(DeribitErrorCode::AuthorizationRequired); // Duplicate
1350
1351        assert_eq!(error_set.len(), 2); // Should only contain 2 unique errors
1352        assert!(error_set.contains(&DeribitErrorCode::AuthorizationRequired));
1353        assert!(error_set.contains(&DeribitErrorCode::Error));
1354        assert!(!error_set.contains(&DeribitErrorCode::Success));
1355    }
1356
1357    #[test]
1358    fn test_display_and_debug_implementations() {
1359        let error = DeribitErrorCode::AuthorizationRequired;
1360        let display_str = format!("{}", error);
1361        let debug_str = format!("{:?}", error);
1362
1363        // Both should contain some representation of the error
1364        assert!(!display_str.is_empty());
1365        assert!(!debug_str.is_empty());
1366
1367        // Test unknown error
1368        let unknown_error = DeribitErrorCode::Unknown(99999);
1369        let unknown_display = format!("{}", unknown_error);
1370        let unknown_debug = format!("{:?}", unknown_error);
1371
1372        assert!(!unknown_display.is_empty());
1373        assert!(!unknown_debug.is_empty());
1374    }
1375}