ledger_sdk_eth_app/
errors.rs1use ledger_sdk_device_base::LedgerAppError;
6use thiserror::Error;
7
8#[derive(Debug, Error, Clone, PartialEq)]
10pub enum EthAppError<E: std::error::Error> {
11 #[error("Transport error: {0}")]
13 Transport(#[from] LedgerAppError<E>),
14
15 #[error("Invalid BIP32 path: {0}")]
17 InvalidBip32Path(String),
18
19 #[error("Invalid Ethereum address: {0}")]
21 InvalidAddress(String),
22
23 #[error("Invalid signature: {0}")]
25 InvalidSignature(String),
26
27 #[error("Transaction data too large: {size} bytes (max {max})")]
29 TransactionTooLarge { size: usize, max: usize },
30
31 #[error("Message data too large: {size} bytes (max {max})")]
33 MessageTooLarge { size: usize, max: usize },
34
35 #[error("Invalid transaction format: {0}")]
37 InvalidTransaction(String),
38
39 #[error("Invalid message format: {0}")]
41 InvalidMessage(String),
42
43 #[error("Hex error: {0}")]
45 HexError(String),
46
47 #[error("Invalid chain ID: {0}")]
49 InvalidChainId(u64),
50
51 #[error("Operation rejected by device")]
53 UserRejected,
54
55 #[error("App configuration error: {0}")]
57 ConfigurationError(String),
58
59 #[error("Feature not supported: {0}")]
61 FeatureNotSupported(String),
62
63 #[error("Chunk error: {0}")]
65 ChunkError(String),
66
67 #[error("Invalid response data: {0}")]
69 InvalidResponseData(String),
70
71 #[error("Invalid EIP-712 data: {0}")]
73 InvalidEip712Data(String),
74
75 #[error("EIP-712 struct error: {0}")]
77 Eip712StructError(String),
78
79 #[error("EIP-712 filter error: {0}")]
81 Eip712FilterError(String),
82
83 #[error("Unsupported version: {0}")]
85 UnsupportedVersion(String),
86
87 #[error("Device status 0x{sw:04X}: {description}")]
89 DeviceStatus { sw: u16, description: String },
90}
91
92impl<E: std::error::Error> EthAppError<E> {
93 pub fn is_user_rejected(&self) -> bool {
95 matches!(self, EthAppError::UserRejected)
96 }
97
98 pub fn is_transport_error(&self) -> bool {
100 matches!(self, EthAppError::Transport(_))
101 }
102
103 pub fn is_invalid_input(&self) -> bool {
105 matches!(
106 self,
107 EthAppError::InvalidBip32Path(_)
108 | EthAppError::InvalidAddress(_)
109 | EthAppError::InvalidSignature(_)
110 | EthAppError::InvalidTransaction(_)
111 | EthAppError::InvalidMessage(_)
112 | EthAppError::InvalidChainId(_)
113 )
114 }
115}
116
117pub type EthAppResult<T, E> = Result<T, EthAppError<E>>;
119
120pub fn map_ledger_error<E: std::error::Error>(err: LedgerAppError<E>) -> EthAppError<E> {
122 match err {
123 LedgerAppError::AppSpecific(0x6982, _) => EthAppError::UserRejected,
125 LedgerAppError::Unknown(0x6982) => EthAppError::UserRejected,
126
127 LedgerAppError::AppSpecific(sw, _) | LedgerAppError::Unknown(sw) => {
129 EthAppError::DeviceStatus {
130 sw,
131 description: describe_eth_status(sw).to_string(),
132 }
133 }
134
135 other => EthAppError::Transport(other),
137 }
138}
139
140fn describe_eth_status(sw: u16) -> &'static str {
142 match sw {
143 0x6001 => "Mode check fail",
144 0x6501 => "TransactionType not supported",
145 0x6502 => "Output buffer too small for chainId conversion",
146 0x6982 => "Security status not satisfied (Canceled by user)",
147 0x6983 => "Wrong Data length",
148 0x6984 => "Plugin not installed",
149 0x6985 => "Condition not satisfied",
150 0x6A00 => "Error without info",
151 0x6A80 => "Invalid data",
152 0x6A84 => "Insufficient memory",
153 0x6A88 => "Data not found",
154 0x6B00 => "Incorrect parameter P1 or P2",
155 0x6D00 => "Incorrect parameter INS",
156 0x6E00 => "Incorrect parameter CLA",
157 0x9000 => "Normal ending of the command",
158 0x911C => "Command code not supported (Ledger-PKI not yet available)",
159 _ if (sw & 0xFF00) == 0x6800 => "Internal error (Please report)",
160 _ if (sw & 0xFF00) == 0x6F00 => "Technical problem (Internal error, please report)",
161 _ => "Unknown status",
162 }
163}