1use crate::{
13 models::{EvmRpcResult, NetworkRpcResult},
14 models::{JsonRpcError, JsonRpcId, JsonRpcResponse},
15};
16use serde_json;
17
18pub fn create_error_response(
32 id: Option<JsonRpcId>,
33 code: i32,
34 message: &str,
35 description: &str,
36) -> JsonRpcResponse<NetworkRpcResult> {
37 JsonRpcResponse {
38 id,
39 jsonrpc: "2.0".to_string(),
40 result: None,
41 error: Some(JsonRpcError {
42 code,
43 message: message.to_string(),
44 description: description.to_string(),
45 }),
46 }
47}
48
49pub fn create_success_response(
61 id: Option<JsonRpcId>,
62 result: serde_json::Value,
63) -> JsonRpcResponse<NetworkRpcResult> {
64 JsonRpcResponse {
65 id,
66 jsonrpc: "2.0".to_string(),
67 result: Some(NetworkRpcResult::Evm(EvmRpcResult::RawRpcResult(result))),
68 error: None,
69 }
70}
71
72pub use crate::utils::{map_provider_error, sanitize_error_description};
75
76#[cfg(test)]
77mod tests {
78 use super::*;
79 use crate::models::{OpenZeppelinErrorCodes, RpcErrorCodes};
80 use serde_json::json;
81
82 #[test]
83 fn test_create_error_response_basic() {
84 let response = create_error_response(
85 Some(JsonRpcId::Number(123)),
86 -32602,
87 "Invalid params",
88 "The provided parameters are invalid",
89 );
90
91 assert_eq!(response.id, Some(JsonRpcId::Number(123)));
92 assert_eq!(response.jsonrpc, "2.0");
93 assert!(response.result.is_none());
94 assert!(response.error.is_some());
95
96 let error = response.error.unwrap();
97 assert_eq!(error.code, -32602);
98 assert!(!error.message.is_empty());
99 assert!(!error.description.is_empty());
100 }
101
102 #[test]
103 fn test_create_error_response_zero_id() {
104 let response = create_error_response(
105 Some(JsonRpcId::Number(0)),
106 -32603,
107 "Internal error",
108 "Something went wrong",
109 );
110
111 assert_eq!(response.id, Some(JsonRpcId::Number(0)));
112 assert_eq!(response.jsonrpc, "2.0");
113 assert!(response.result.is_none());
114 assert!(response.error.is_some());
115 }
116
117 #[test]
118 fn test_create_error_response_max_id() {
119 let response = create_error_response(
120 Some(JsonRpcId::Number(u64::MAX as i64)),
121 -32700,
122 "Parse error",
123 "JSON parsing failed",
124 );
125
126 assert_eq!(response.id, Some(JsonRpcId::Number(u64::MAX as i64)));
127 assert_eq!(response.jsonrpc, "2.0");
128 assert!(response.result.is_none());
129 assert!(response.error.is_some());
130 }
131
132 #[test]
133 fn test_create_error_response_empty_message() {
134 let response = create_error_response(
135 Some(JsonRpcId::Number(42)),
136 -32601,
137 "",
138 "Method not found error",
139 );
140
141 assert_eq!(response.id, Some(JsonRpcId::Number(42)));
142 let error = response.error.unwrap();
143 assert!(error.message.is_empty());
144 assert!(!error.description.is_empty());
145 }
146
147 #[test]
148 fn test_create_error_response_empty_description() {
149 let response =
150 create_error_response(Some(JsonRpcId::Number(99)), -32600, "Invalid Request", "");
151
152 assert_eq!(response.id, Some(JsonRpcId::Number(99)));
153 let error = response.error.unwrap();
154 assert!(!error.message.is_empty());
155 assert!(error.description.is_empty());
156 }
157
158 #[test]
159 fn test_create_error_response_preserves_input() {
160 let message = "Error with unicode: 🚨 ñáéÃóú";
161 let description = "Description with symbols: @#$%^&*()";
162 let response =
163 create_error_response(Some(JsonRpcId::Number(500)), -33000, message, description);
164
165 let error = response.error.unwrap();
166 assert!(!error.message.is_empty());
167 assert!(!error.description.is_empty());
168 assert_eq!(error.code, -33000);
169 }
170
171 #[test]
172 fn test_create_error_response_long_strings() {
173 let long_message = "a".repeat(1000);
174 let long_description = "b".repeat(2000);
175 let response = create_error_response(
176 Some(JsonRpcId::Number(777)),
177 -33001,
178 &long_message,
179 &long_description,
180 );
181
182 let error = response.error.unwrap();
183 assert_eq!(error.message.len(), 1000);
184 assert_eq!(error.description.len(), 2000);
185 }
186
187 #[test]
188 fn test_create_error_response_custom_openzeppelin_codes() {
189 let test_cases = vec![
190 OpenZeppelinErrorCodes::TIMEOUT,
191 OpenZeppelinErrorCodes::RATE_LIMITED,
192 OpenZeppelinErrorCodes::BAD_GATEWAY,
193 OpenZeppelinErrorCodes::REQUEST_ERROR,
194 OpenZeppelinErrorCodes::NETWORK_CONFIGURATION,
195 ];
196
197 for code in test_cases {
198 let response = create_error_response(
199 Some(JsonRpcId::Number(1)),
200 code,
201 "Test message",
202 "Test description",
203 );
204 let error = response.error.unwrap();
205 assert_eq!(error.code, code);
206 assert!(!error.message.is_empty());
207 assert!(!error.description.is_empty());
208 }
209 }
210
211 #[test]
212 fn test_create_error_response_standard_json_rpc_codes() {
213 let test_cases = vec![
214 RpcErrorCodes::PARSE,
215 RpcErrorCodes::INVALID_REQUEST,
216 RpcErrorCodes::METHOD_NOT_FOUND,
217 RpcErrorCodes::INVALID_PARAMS,
218 RpcErrorCodes::INTERNAL_ERROR,
219 ];
220
221 for code in test_cases {
222 let response = create_error_response(
223 Some(JsonRpcId::Number(1)),
224 code,
225 "Test message",
226 "Test description",
227 );
228 let error = response.error.unwrap();
229 assert_eq!(error.code, code);
230 assert!(!error.message.is_empty());
231 assert!(!error.description.is_empty());
232 }
233 }
234
235 #[test]
236 fn test_create_success_response_basic() {
237 let result_data = json!({
238 "blockNumber": "0x1234",
239 "hash": "0xabcd"
240 });
241
242 let response = create_success_response(Some(JsonRpcId::Number(456)), result_data.clone());
243
244 assert_eq!(response.id, Some(JsonRpcId::Number(456)));
245 assert_eq!(response.jsonrpc, "2.0");
246 assert!(response.error.is_none());
247 assert!(response.result.is_some());
248
249 match response.result.unwrap() {
250 NetworkRpcResult::Evm(EvmRpcResult::RawRpcResult(value)) => {
251 assert_eq!(value, result_data);
252 }
253 _ => unreachable!("Expected EVM RawRpcResult"),
254 }
255 }
256
257 #[test]
258 fn test_create_success_response_zero_id() {
259 let result_data = json!(null);
260 let response = create_success_response(Some(JsonRpcId::Number(0)), result_data);
261
262 assert_eq!(response.id, Some(JsonRpcId::Number(0)));
263 assert_eq!(response.jsonrpc, "2.0");
264 assert!(response.error.is_none());
265 }
266
267 #[test]
268 fn test_create_success_response_max_id() {
269 let result_data = json!(42);
270 let response =
271 create_success_response(Some(JsonRpcId::Number(u64::MAX as i64)), result_data);
272
273 assert_eq!(response.id, Some(JsonRpcId::Number(u64::MAX as i64)));
274 assert_eq!(response.jsonrpc, "2.0");
275 assert!(response.error.is_none());
276 }
277
278 #[test]
279 fn test_create_success_response_null_result() {
280 let result_data = json!(null);
281 let response = create_success_response(Some(JsonRpcId::Number(100)), result_data.clone());
282
283 match response.result.unwrap() {
284 NetworkRpcResult::Evm(EvmRpcResult::RawRpcResult(value)) => {
285 assert_eq!(value, result_data);
286 assert!(value.is_null());
287 }
288 _ => unreachable!("Expected EVM RawRpcResult"),
289 }
290 }
291
292 #[test]
293 fn test_create_success_response_boolean_result() {
294 let result_data = json!(true);
295 let response = create_success_response(Some(JsonRpcId::Number(200)), result_data.clone());
296
297 match response.result.unwrap() {
298 NetworkRpcResult::Evm(EvmRpcResult::RawRpcResult(value)) => {
299 assert_eq!(value, result_data);
300 assert!(value.is_boolean());
301 }
302 _ => unreachable!("Expected EVM RawRpcResult"),
303 }
304 }
305
306 #[test]
307 fn test_create_success_response_number_result() {
308 let result_data = json!(12345);
309 let response = create_success_response(Some(JsonRpcId::Number(300)), result_data.clone());
310
311 match response.result.unwrap() {
312 NetworkRpcResult::Evm(EvmRpcResult::RawRpcResult(value)) => {
313 assert_eq!(value, result_data);
314 assert!(value.is_number());
315 }
316 _ => unreachable!("Expected EVM RawRpcResult"),
317 }
318 }
319
320 #[test]
321 fn test_create_success_response_string_result() {
322 let result_data = json!("test string");
323 let response = create_success_response(Some(JsonRpcId::Number(400)), result_data.clone());
324
325 match response.result.unwrap() {
326 NetworkRpcResult::Evm(EvmRpcResult::RawRpcResult(value)) => {
327 assert_eq!(value, result_data);
328 assert!(value.is_string());
329 }
330 _ => unreachable!("Expected EVM RawRpcResult"),
331 }
332 }
333
334 #[test]
335 fn test_create_success_response_array_result() {
336 let result_data = json!([1, 2, 3, "test", true, null]);
337 let response = create_success_response(Some(JsonRpcId::Number(500)), result_data.clone());
338
339 match response.result.unwrap() {
340 NetworkRpcResult::Evm(EvmRpcResult::RawRpcResult(value)) => {
341 assert_eq!(value, result_data);
342 assert!(value.is_array());
343 assert_eq!(value.as_array().unwrap().len(), 6);
344 }
345 _ => unreachable!("Expected EVM RawRpcResult"),
346 }
347 }
348
349 #[test]
350 fn test_create_success_response_complex_object() {
351 let result_data = json!({
352 "transactions": [
353 {"hash": "0x123", "value": "1000000000000000000"},
354 {"hash": "0x456", "value": "2000000000000000000"}
355 ],
356 "blockNumber": "0x1a2b3c",
357 "timestamp": 1234567890,
358 "gasUsed": "0x5208",
359 "metadata": {
360 "network": "mainnet",
361 "version": "1.0",
362 "features": ["eip1559", "eip2930"]
363 },
364 "isEmpty": false,
365 "nullField": null
366 });
367
368 let response = create_success_response(Some(JsonRpcId::Number(600)), result_data.clone());
369
370 match response.result.unwrap() {
371 NetworkRpcResult::Evm(EvmRpcResult::RawRpcResult(value)) => {
372 assert_eq!(value, result_data);
373 assert!(value.is_object());
374 assert_eq!(value["blockNumber"], "0x1a2b3c");
375 assert_eq!(value["transactions"].as_array().unwrap().len(), 2);
376 assert!(value["nullField"].is_null());
377 }
378 _ => unreachable!("Expected EVM RawRpcResult"),
379 }
380 }
381
382 #[test]
383 fn test_create_success_response_large_object() {
384 let mut large_object = json!({});
385 let object = large_object.as_object_mut().unwrap();
386
387 for i in 0..100 {
389 object.insert(format!("field_{i}"), json!(format!("value_{}", i)));
390 }
391
392 let response = create_success_response(Some(JsonRpcId::Number(700)), large_object.clone());
393
394 match response.result.unwrap() {
395 NetworkRpcResult::Evm(EvmRpcResult::RawRpcResult(value)) => {
396 assert_eq!(value, large_object);
397 assert_eq!(value.as_object().unwrap().len(), 100);
398 }
399 _ => unreachable!("Expected EVM RawRpcResult"),
400 }
401 }
402
403 #[test]
404 fn test_integration_error_response_with_mapped_provider_error() {
405 use crate::models::RpcErrorCodes;
406 use crate::services::provider::ProviderError;
407 use crate::utils::map_provider_error;
408
409 let provider_error = ProviderError::InvalidAddress("0xinvalid".to_string());
410 let (error_code, error_message) = map_provider_error(&provider_error);
411
412 let response = create_error_response(
413 Some(JsonRpcId::Number(999)),
414 error_code,
415 error_message,
416 "Invalid address provided",
417 );
418
419 assert_eq!(response.id, Some(JsonRpcId::Number(999)));
420 assert_eq!(response.jsonrpc, "2.0");
421 assert!(response.result.is_none());
422
423 let error = response.error.unwrap();
424 assert_eq!(error.code, RpcErrorCodes::INVALID_PARAMS);
425 assert!(!error.message.is_empty());
426 assert!(!error.description.is_empty());
427 }
428
429 #[test]
430 fn test_integration_all_provider_errors_to_responses() {
431 use crate::models::{OpenZeppelinErrorCodes, RpcErrorCodes};
432 use crate::services::provider::ProviderError;
433 use crate::utils::map_provider_error;
434
435 let test_cases = vec![
436 (
437 ProviderError::InvalidAddress("test".to_string()),
438 RpcErrorCodes::INVALID_PARAMS,
439 ),
440 (
441 ProviderError::NetworkConfiguration("test".to_string()),
442 OpenZeppelinErrorCodes::NETWORK_CONFIGURATION,
443 ),
444 (ProviderError::Timeout, OpenZeppelinErrorCodes::TIMEOUT),
445 (
446 ProviderError::RateLimited,
447 OpenZeppelinErrorCodes::RATE_LIMITED,
448 ),
449 (
450 ProviderError::BadGateway,
451 OpenZeppelinErrorCodes::BAD_GATEWAY,
452 ),
453 (
454 ProviderError::RequestError {
455 error: "test".to_string(),
456 status_code: 400,
457 },
458 OpenZeppelinErrorCodes::REQUEST_ERROR,
459 ),
460 (
461 ProviderError::Other("test".to_string()),
462 RpcErrorCodes::INTERNAL_ERROR,
463 ),
464 ];
465
466 for (provider_error, expected_code) in test_cases {
467 let (error_code, error_message) = map_provider_error(&provider_error);
468 let response = create_error_response(
469 Some(JsonRpcId::Number(1)),
470 error_code,
471 error_message,
472 "Test integration",
473 );
474
475 assert_eq!(response.id, Some(JsonRpcId::Number(1)));
476 assert_eq!(response.jsonrpc, "2.0");
477 assert!(response.result.is_none());
478
479 let error = response.error.unwrap();
480 assert_eq!(error.code, expected_code);
481 assert!(!error.message.is_empty());
482 }
483 }
484
485 #[test]
486 fn test_response_structure_consistency() {
487 let success_response =
489 create_success_response(Some(JsonRpcId::Number(100)), json!({"status": "ok"}));
490 let error_response = create_error_response(
491 Some(JsonRpcId::Number(100)),
492 -32603,
493 "Internal error",
494 "Test error",
495 );
496
497 assert_eq!(success_response.id, error_response.id);
499 assert_eq!(success_response.jsonrpc, error_response.jsonrpc);
500
501 assert!(success_response.result.is_some());
503 assert!(success_response.error.is_none());
504
505 assert!(error_response.result.is_none());
507 assert!(error_response.error.is_some());
508 }
509}