openzeppelin_relayer/utils/
json_rpc_error.rs1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5pub enum StandardJsonRpcError {
6 ParseError = -32700,
8 InvalidRequest = -32600,
10 MethodNotFound = -32601,
12 InvalidParams = -32602,
14 InternalError = -32603,
16}
17
18#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20pub enum EthereumJsonRpcError {
21 InvalidInput = -32000,
23 ResourceNotFound = -32001,
25 ResourceUnavailable = -32002,
27 TransactionRejected = -32003,
29 MethodNotSupported = -32004,
31 LimitExceeded = -32005,
33 JsonRpcVersionNotSupported = -32006,
35}
36
37impl StandardJsonRpcError {
38 pub const fn code(self) -> i64 {
39 self as i64
40 }
41
42 pub const fn from_code(code: i64) -> Option<Self> {
43 match code {
44 -32700 => Some(Self::ParseError),
45 -32600 => Some(Self::InvalidRequest),
46 -32601 => Some(Self::MethodNotFound),
47 -32602 => Some(Self::InvalidParams),
48 -32603 => Some(Self::InternalError),
49 _ => None,
50 }
51 }
52}
53
54impl EthereumJsonRpcError {
55 pub const fn code(self) -> i64 {
56 self as i64
57 }
58
59 pub const fn from_code(code: i64) -> Option<Self> {
60 match code {
61 -32000 => Some(Self::InvalidInput),
62 -32001 => Some(Self::ResourceNotFound),
63 -32002 => Some(Self::ResourceUnavailable),
64 -32003 => Some(Self::TransactionRejected),
65 -32004 => Some(Self::MethodNotSupported),
66 -32005 => Some(Self::LimitExceeded),
67 -32006 => Some(Self::JsonRpcVersionNotSupported),
68 _ => None,
69 }
70 }
71}
72
73pub const fn is_retriable_error_code(code: i64) -> bool {
75 code == StandardJsonRpcError::InternalError as i64
76 || code == EthereumJsonRpcError::ResourceUnavailable as i64
77 || code == EthereumJsonRpcError::LimitExceeded as i64
78}
79
80#[cfg(test)]
81mod tests {
82 use super::*;
83
84 #[test]
85 fn test_standard_error_code_values() {
86 assert_eq!(StandardJsonRpcError::ParseError.code(), -32700);
87 assert_eq!(StandardJsonRpcError::InvalidRequest.code(), -32600);
88 assert_eq!(StandardJsonRpcError::MethodNotFound.code(), -32601);
89 assert_eq!(StandardJsonRpcError::InvalidParams.code(), -32602);
90 assert_eq!(StandardJsonRpcError::InternalError.code(), -32603);
91 }
92
93 #[test]
94 fn test_ethereum_error_code_values() {
95 assert_eq!(EthereumJsonRpcError::InvalidInput.code(), -32000);
96 assert_eq!(EthereumJsonRpcError::ResourceNotFound.code(), -32001);
97 assert_eq!(EthereumJsonRpcError::ResourceUnavailable.code(), -32002);
98 assert_eq!(EthereumJsonRpcError::TransactionRejected.code(), -32003);
99 assert_eq!(EthereumJsonRpcError::MethodNotSupported.code(), -32004);
100 assert_eq!(EthereumJsonRpcError::LimitExceeded.code(), -32005);
101 assert_eq!(
102 EthereumJsonRpcError::JsonRpcVersionNotSupported.code(),
103 -32006
104 );
105 }
106
107 #[test]
108 fn test_standard_error_from_code_valid() {
109 assert_eq!(
110 StandardJsonRpcError::from_code(-32700),
111 Some(StandardJsonRpcError::ParseError)
112 );
113 assert_eq!(
114 StandardJsonRpcError::from_code(-32600),
115 Some(StandardJsonRpcError::InvalidRequest)
116 );
117 assert_eq!(
118 StandardJsonRpcError::from_code(-32601),
119 Some(StandardJsonRpcError::MethodNotFound)
120 );
121 assert_eq!(
122 StandardJsonRpcError::from_code(-32602),
123 Some(StandardJsonRpcError::InvalidParams)
124 );
125 assert_eq!(
126 StandardJsonRpcError::from_code(-32603),
127 Some(StandardJsonRpcError::InternalError)
128 );
129 }
130
131 #[test]
132 fn test_standard_error_from_code_invalid() {
133 assert_eq!(StandardJsonRpcError::from_code(-32000), None);
134 assert_eq!(StandardJsonRpcError::from_code(-32699), None);
135 assert_eq!(StandardJsonRpcError::from_code(0), None);
136 assert_eq!(StandardJsonRpcError::from_code(500), None);
137 }
138
139 #[test]
140 fn test_ethereum_error_from_code_valid() {
141 assert_eq!(
142 EthereumJsonRpcError::from_code(-32000),
143 Some(EthereumJsonRpcError::InvalidInput)
144 );
145 assert_eq!(
146 EthereumJsonRpcError::from_code(-32001),
147 Some(EthereumJsonRpcError::ResourceNotFound)
148 );
149 assert_eq!(
150 EthereumJsonRpcError::from_code(-32002),
151 Some(EthereumJsonRpcError::ResourceUnavailable)
152 );
153 assert_eq!(
154 EthereumJsonRpcError::from_code(-32003),
155 Some(EthereumJsonRpcError::TransactionRejected)
156 );
157 assert_eq!(
158 EthereumJsonRpcError::from_code(-32004),
159 Some(EthereumJsonRpcError::MethodNotSupported)
160 );
161 assert_eq!(
162 EthereumJsonRpcError::from_code(-32005),
163 Some(EthereumJsonRpcError::LimitExceeded)
164 );
165 assert_eq!(
166 EthereumJsonRpcError::from_code(-32006),
167 Some(EthereumJsonRpcError::JsonRpcVersionNotSupported)
168 );
169 }
170
171 #[test]
172 fn test_ethereum_error_from_code_invalid() {
173 assert_eq!(EthereumJsonRpcError::from_code(-32700), None);
174 assert_eq!(EthereumJsonRpcError::from_code(-32007), None);
175 assert_eq!(EthereumJsonRpcError::from_code(-31999), None);
176 assert_eq!(EthereumJsonRpcError::from_code(0), None);
177 }
178
179 #[test]
180 fn test_is_retriable_error_code_retriable() {
181 assert!(is_retriable_error_code(-32603));
182 assert!(is_retriable_error_code(-32002));
183 assert!(is_retriable_error_code(-32005));
184 }
185
186 #[test]
187 fn test_is_retriable_error_code_non_retriable_standard() {
188 assert!(!is_retriable_error_code(-32700));
189 assert!(!is_retriable_error_code(-32600));
190 assert!(!is_retriable_error_code(-32601));
191 assert!(!is_retriable_error_code(-32602));
192 }
193
194 #[test]
195 fn test_is_retriable_error_code_non_retriable_ethereum() {
196 assert!(!is_retriable_error_code(-32000));
197 assert!(!is_retriable_error_code(-32001));
198 assert!(!is_retriable_error_code(-32003));
199 assert!(!is_retriable_error_code(-32004));
200 assert!(!is_retriable_error_code(-32006));
201 }
202
203 #[test]
204 fn test_is_retriable_error_code_unknown() {
205 assert!(!is_retriable_error_code(0));
206 assert!(!is_retriable_error_code(404));
207 assert!(!is_retriable_error_code(500));
208 assert!(!is_retriable_error_code(-1));
209 assert!(!is_retriable_error_code(-32100));
210 assert!(!is_retriable_error_code(-32769));
211 assert!(!is_retriable_error_code(-31999));
212 }
213
214 #[test]
215 fn test_standard_error_roundtrip() {
216 let errors = [
217 StandardJsonRpcError::ParseError,
218 StandardJsonRpcError::InvalidRequest,
219 StandardJsonRpcError::MethodNotFound,
220 StandardJsonRpcError::InvalidParams,
221 StandardJsonRpcError::InternalError,
222 ];
223
224 for error in errors {
225 let code = error.code();
226 let reconstructed = StandardJsonRpcError::from_code(code);
227 assert_eq!(reconstructed, Some(error));
228 }
229 }
230
231 #[test]
232 fn test_ethereum_error_roundtrip() {
233 let errors = [
234 EthereumJsonRpcError::InvalidInput,
235 EthereumJsonRpcError::ResourceNotFound,
236 EthereumJsonRpcError::ResourceUnavailable,
237 EthereumJsonRpcError::TransactionRejected,
238 EthereumJsonRpcError::MethodNotSupported,
239 EthereumJsonRpcError::LimitExceeded,
240 EthereumJsonRpcError::JsonRpcVersionNotSupported,
241 ];
242
243 for error in errors {
244 let code = error.code();
245 let reconstructed = EthereumJsonRpcError::from_code(code);
246 assert_eq!(reconstructed, Some(error));
247 }
248 }
249}