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******************************************************************************/
6
7use crate::{impl_json_debug_pretty, impl_json_display};
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(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// JSON display and debug implementations
492impl_json_display!(DeribitErrorCode);
493impl_json_debug_pretty!(DeribitErrorCode);
494
495// Conversion from DeribitErrorCode to i32 (required for serde)
496impl From<DeribitErrorCode> for i32 {
497    fn from(error: DeribitErrorCode) -> Self {
498        match error {
499            DeribitErrorCode::Success => 0,
500            DeribitErrorCode::AuthorizationRequired => 10000,
501            DeribitErrorCode::Error => 10001,
502            DeribitErrorCode::QtyTooLow => 10002,
503            DeribitErrorCode::OrderOverlap => 10003,
504            DeribitErrorCode::OrderNotFound => 10004,
505            DeribitErrorCode::PriceTooLow => 10005,
506            DeribitErrorCode::PriceTooLow4Idx => 10006,
507            DeribitErrorCode::PriceTooHigh => 10007,
508            DeribitErrorCode::NotEnoughFunds => 10009,
509            DeribitErrorCode::AlreadyClosed => 10010,
510            DeribitErrorCode::PriceNotAllowed => 10011,
511            DeribitErrorCode::BookClosed => 10012,
512            DeribitErrorCode::PmeMaxTotalOpenOrders => 10013,
513            DeribitErrorCode::PmeMaxFutureOpenOrders => 10014,
514            DeribitErrorCode::PmeMaxOptionOpenOrders => 10015,
515            DeribitErrorCode::PmeMaxFutureOpenOrdersSize => 10016,
516            DeribitErrorCode::PmeMaxOptionOpenOrdersSize => 10017,
517            DeribitErrorCode::NonPmeMaxFuturePositionSize => 10018,
518            DeribitErrorCode::LockedByAdmin => 10019,
519            DeribitErrorCode::InvalidOrUnsupportedInstrument => 10020,
520            DeribitErrorCode::InvalidAmount => 10021,
521            DeribitErrorCode::InvalidQuantity => 10022,
522            DeribitErrorCode::InvalidPrice => 10023,
523            DeribitErrorCode::InvalidMaxShow => 10024,
524            DeribitErrorCode::InvalidOrderId => 10025,
525            DeribitErrorCode::PricePrecisionExceeded => 10026,
526            DeribitErrorCode::NonIntegerContractAmount => 10027,
527            DeribitErrorCode::TooManyRequests => 10028,
528            DeribitErrorCode::NotOwnerOfOrder => 10029,
529            DeribitErrorCode::MustBeWebsocketRequest => 10030,
530            DeribitErrorCode::InvalidArgsForInstrument => 10031,
531            DeribitErrorCode::WholeCostTooLow => 10032,
532            DeribitErrorCode::NotImplemented => 10033,
533            DeribitErrorCode::TriggerPriceTooHigh => 10034,
534            DeribitErrorCode::TriggerPriceTooLow => 10035,
535            DeribitErrorCode::InvalidMaxShowAmount => 10036,
536            DeribitErrorCode::NonPmeTotalShortOptionsPositionsSize => 10037,
537            DeribitErrorCode::PmeMaxRiskReducingOrders => 10038,
538            DeribitErrorCode::NotEnoughFundsInCurrency => 10039,
539            DeribitErrorCode::Retry => 10040,
540            DeribitErrorCode::SettlementInProgress => 10041,
541            DeribitErrorCode::PriceWrongTick => 10043,
542            DeribitErrorCode::TriggerPriceWrongTick => 10044,
543            DeribitErrorCode::CanNotCancelLiquidationOrder => 10045,
544            DeribitErrorCode::CanNotEditLiquidationOrder => 10046,
545            DeribitErrorCode::MatchingEngineQueueFull => 10047,
546            DeribitErrorCode::NotOnThisServer => 10048,
547            DeribitErrorCode::CancelOnDisconnectFailed => 10049,
548            DeribitErrorCode::TooManyConcurrentRequests => 10066,
549            DeribitErrorCode::DisabledWhilePositionLock => 10072,
550            DeribitErrorCode::AlreadyFilled => 11008,
551            DeribitErrorCode::MaxSpotOpenOrders => 11013,
552            DeribitErrorCode::PostOnlyPriceModificationNotPossible => 11021,
553            DeribitErrorCode::MaxSpotOrderQuantity => 11022,
554            DeribitErrorCode::InvalidArguments => 11029,
555            DeribitErrorCode::OtherReject => 11030,
556            DeribitErrorCode::OtherError => 11031,
557            DeribitErrorCode::NoMoreTriggers => 11035,
558            DeribitErrorCode::InvalidTriggerPrice => 11036,
559            DeribitErrorCode::OutdatedInstrumentForIvOrder => 11037,
560            DeribitErrorCode::NoAdvForFutures => 11038,
561            DeribitErrorCode::NoAdvPostonly => 11039,
562            DeribitErrorCode::NotAdvOrder => 11041,
563            DeribitErrorCode::PermissionDenied => 11042,
564            DeribitErrorCode::BadArgument => 11043,
565            DeribitErrorCode::NotOpenOrder => 11044,
566            DeribitErrorCode::InvalidEvent => 11045,
567            DeribitErrorCode::OutdatedInstrument => 11046,
568            DeribitErrorCode::UnsupportedArgCombination => 11047,
569            DeribitErrorCode::WrongMaxShowForOption => 11048,
570            DeribitErrorCode::BadArguments => 11049,
571            DeribitErrorCode::BadRequest => 11050,
572            DeribitErrorCode::SystemMaintenance => 11051,
573            DeribitErrorCode::SubscribeErrorUnsubscribed => 11052,
574            DeribitErrorCode::TransferNotFound => 11053,
575            DeribitErrorCode::PostOnlyReject => 11054,
576            DeribitErrorCode::PostOnlyNotAllowed => 11055,
577            DeribitErrorCode::UnauthenticatedPublicRequestsTemporarilyDisabled => 11056,
578            DeribitErrorCode::InvalidAddr => 11090,
579            DeribitErrorCode::InvalidTransferAddress => 11091,
580            DeribitErrorCode::AddressAlreadyExist => 11092,
581            DeribitErrorCode::MaxAddrCountExceeded => 11093,
582            DeribitErrorCode::InternalServerError => 11094,
583            DeribitErrorCode::DisabledDepositAddressCreation => 11095,
584            DeribitErrorCode::AddressBelongsToUser => 11096,
585            DeribitErrorCode::NoDepositAddress => 11097,
586            DeribitErrorCode::AccountLocked => 11098,
587            DeribitErrorCode::TooManySubaccounts => 12001,
588            DeribitErrorCode::WrongSubaccountName => 12002,
589            DeribitErrorCode::LoginOverLimit => 12003,
590            DeribitErrorCode::RegistrationOverLimit => 12004,
591            DeribitErrorCode::CountryIsBanned => 12005,
592            DeribitErrorCode::TransferNotAllowed => 12100,
593            DeribitErrorCode::SecurityKeyAuthorizationOverLimit => 12998,
594            DeribitErrorCode::InvalidCredentials => 13004,
595            DeribitErrorCode::PwdMatchError => 13005,
596            DeribitErrorCode::SecurityError => 13006,
597            DeribitErrorCode::UserNotFound => 13007,
598            DeribitErrorCode::RequestFailed => 13008,
599            DeribitErrorCode::Unauthorized => 13009,
600            DeribitErrorCode::ValueRequired => 13010,
601            DeribitErrorCode::ValueTooShort => 13011,
602            DeribitErrorCode::UnavailableInSubaccount => 13012,
603            DeribitErrorCode::InvalidPhoneNumber => 13013,
604            DeribitErrorCode::CannotSendSms => 13014,
605            DeribitErrorCode::InvalidSmsCode => 13015,
606            DeribitErrorCode::InvalidInput => 13016,
607            DeribitErrorCode::InvalidContentType => 13018,
608            DeribitErrorCode::OrderbookClosed => 13019,
609            DeribitErrorCode::NotFound => 13020,
610            DeribitErrorCode::Forbidden => 13021,
611            DeribitErrorCode::MethodSwitchedOffByAdmin => 13025,
612            DeribitErrorCode::TemporarilyUnavailable => 13028,
613            DeribitErrorCode::MmpTrigger => 13030,
614            DeribitErrorCode::VerificationRequired => 13031,
615            DeribitErrorCode::NonUniqueOrderLabel => 13032,
616            DeribitErrorCode::NoMoreSecurityKeysAllowed => 13034,
617            DeribitErrorCode::ActiveComboLimitReached => 13035,
618            DeribitErrorCode::UnavailableForComboBooks => 13036,
619            DeribitErrorCode::IncompleteKycData => 13037,
620            DeribitErrorCode::MmpRequired => 13040,
621            DeribitErrorCode::CodNotEnabled => 13042,
622            DeribitErrorCode::QuotesFrozen => 13043,
623            DeribitErrorCode::ScopeExceeded => 13403,
624            DeribitErrorCode::Unavailable => 13503,
625            DeribitErrorCode::RequestCancelledByUser => 13666,
626            DeribitErrorCode::Replaced => 13777,
627            DeribitErrorCode::RawSubscriptionsNotAvailableForUnauthorized => 13778,
628            DeribitErrorCode::MovePositionsOverLimit => 13780,
629            DeribitErrorCode::CouponAlreadyUsed => 13781,
630            DeribitErrorCode::KycTransferAlreadyInitiated => 13791,
631            DeribitErrorCode::Unknown(code) => code,
632        }
633    }
634}
635
636#[cfg(test)]
637mod tests {
638    use super::*;
639
640    #[test]
641    fn test_error_code_conversion() {
642        let error = DeribitErrorCode::from(10000);
643        assert_eq!(error, DeribitErrorCode::AuthorizationRequired);
644        assert_eq!(error.code(), 10000);
645        assert_eq!(error.message(), "authorization_required");
646    }
647
648    #[test]
649    fn test_unknown_error_code() {
650        let error = DeribitErrorCode::from(99999);
651        assert_eq!(error, DeribitErrorCode::Unknown(99999));
652        assert_eq!(error.code(), 99999);
653        assert_eq!(error.message(), "unknown_error");
654    }
655
656    #[test]
657    fn test_success_code() {
658        let error = DeribitErrorCode::from(0);
659        assert_eq!(error, DeribitErrorCode::Success);
660        assert!(error.is_success());
661        assert!(!error.is_authorization_error());
662    }
663
664    #[test]
665    fn test_error_categorization() {
666        let auth_error = DeribitErrorCode::AuthorizationRequired;
667        assert!(auth_error.is_authorization_error());
668        assert!(!auth_error.is_trading_error());
669
670        let trading_error = DeribitErrorCode::QtyTooLow;
671        assert!(trading_error.is_trading_error());
672        assert!(!trading_error.is_authorization_error());
673
674        let rate_limit_error = DeribitErrorCode::TooManyRequests;
675        assert!(rate_limit_error.is_rate_limit_error());
676        assert!(!rate_limit_error.is_validation_error());
677
678        let validation_error = DeribitErrorCode::InvalidAmount;
679        assert!(validation_error.is_validation_error());
680        assert!(!validation_error.is_rate_limit_error());
681    }
682
683    #[test]
684    fn test_serde_serialization() {
685        let error = DeribitErrorCode::AuthorizationRequired;
686        let json = serde_json::to_string(&error).unwrap();
687        assert_eq!(json, "10000");
688
689        let deserialized: DeribitErrorCode = serde_json::from_str(&json).unwrap();
690        assert_eq!(deserialized, error);
691    }
692
693    #[test]
694    fn test_specific_error_codes() {
695        // Test some key error codes to ensure they map correctly
696        assert_eq!(DeribitErrorCode::from(0), DeribitErrorCode::Success);
697        assert_eq!(DeribitErrorCode::from(10001), DeribitErrorCode::Error);
698        assert_eq!(DeribitErrorCode::from(10002), DeribitErrorCode::QtyTooLow);
699        assert_eq!(
700            DeribitErrorCode::from(13009),
701            DeribitErrorCode::Unauthorized
702        );
703        assert_eq!(DeribitErrorCode::from(13020), DeribitErrorCode::NotFound);
704
705        // Test reverse conversion
706        assert_eq!(DeribitErrorCode::Success.code(), 0);
707        assert_eq!(DeribitErrorCode::AuthorizationRequired.code(), 10000);
708        assert_eq!(DeribitErrorCode::TooManyRequests.code(), 10028);
709    }
710}