openzeppelin_relayer/api/routes/
network.rs1use crate::{
6 api::controllers::network,
7 models::{DefaultAppState, PaginationQuery, UpdateNetworkRequest},
8};
9use actix_web::{get, patch, web, Responder};
10
11#[get("/networks")]
13async fn list_networks(
14 query: web::Query<PaginationQuery>,
15 data: web::ThinData<DefaultAppState>,
16) -> impl Responder {
17 network::list_networks(query.into_inner(), data).await
18}
19
20#[get("/networks/{network_id}")]
22async fn get_network(
23 network_id: web::Path<String>,
24 data: web::ThinData<DefaultAppState>,
25) -> impl Responder {
26 network::get_network(network_id.into_inner(), data).await
27}
28
29#[patch("/networks/{network_id}")]
32async fn update_network(
33 network_id: web::Path<String>,
34 request: web::Json<UpdateNetworkRequest>,
35 data: web::ThinData<DefaultAppState>,
36) -> impl Responder {
37 network::update_network(network_id.into_inner(), request.into_inner(), data).await
38}
39
40pub fn init(cfg: &mut web::ServiceConfig) {
42 cfg.service(update_network); cfg.service(get_network); cfg.service(list_networks); }
47
48#[cfg(test)]
49mod tests {
50 use super::*;
51 use crate::utils::mocks::mockutils::create_mock_app_state;
52 use actix_web::{http::StatusCode, test, App};
53
54 #[actix_web::test]
59 async fn test_network_routes_are_registered() {
60 let app_state = create_mock_app_state(None, None, None, None, None, None).await;
62 let app = test::init_service(
63 App::new()
64 .app_data(web::Data::new(app_state))
65 .configure(init),
66 )
67 .await;
68
69 let req = test::TestRequest::get().uri("/networks").to_request();
71 let resp = test::call_service(&app, req).await;
72 assert_ne!(
73 resp.status(),
74 StatusCode::NOT_FOUND,
75 "GET /networks route not registered"
76 );
77
78 let req = test::TestRequest::get()
80 .uri("/networks/evm:sepolia")
81 .to_request();
82 let resp = test::call_service(&app, req).await;
83 assert_ne!(
84 resp.status(),
85 StatusCode::NOT_FOUND,
86 "GET /networks/{{network_id}} route not registered"
87 );
88
89 let req = test::TestRequest::patch()
91 .uri("/networks/evm:sepolia")
92 .set_json(serde_json::json!({
93 "rpc_urls": ["https://rpc.example.com"]
94 }))
95 .to_request();
96 let resp = test::call_service(&app, req).await;
97 assert_ne!(
98 resp.status(),
99 StatusCode::NOT_FOUND,
100 "PATCH /networks/{{network_id}} route not registered"
101 );
102 }
103
104 #[actix_web::test]
105 async fn test_network_routes_with_query_params() {
106 let app_state = create_mock_app_state(None, None, None, None, None, None).await;
108 let app = test::init_service(
109 App::new()
110 .app_data(web::Data::new(app_state))
111 .configure(init),
112 )
113 .await;
114
115 let req = test::TestRequest::get()
117 .uri("/networks?page=1&per_page=10")
118 .to_request();
119 let resp = test::call_service(&app, req).await;
120 assert_ne!(
121 resp.status(),
122 StatusCode::NOT_FOUND,
123 "GET /networks with query params route not registered"
124 );
125 }
126
127 #[actix_web::test]
128 async fn test_network_routes_with_special_characters_in_path() {
129 let app_state = create_mock_app_state(None, None, None, None, None, None).await;
131 let app = test::init_service(
132 App::new()
133 .app_data(web::Data::new(app_state))
134 .configure(init),
135 )
136 .await;
137
138 let req = test::TestRequest::get()
140 .uri("/networks/evm:mainnet")
141 .to_request();
142 let resp = test::call_service(&app, req).await;
143 assert_ne!(
144 resp.status(),
145 StatusCode::NOT_FOUND,
146 "GET /networks/evm:mainnet route should handle colon in path"
147 );
148
149 let req = test::TestRequest::get()
150 .uri("/networks/solana:devnet")
151 .to_request();
152 let resp = test::call_service(&app, req).await;
153 assert_ne!(
154 resp.status(),
155 StatusCode::NOT_FOUND,
156 "GET /networks/solana:devnet route should handle colon in path"
157 );
158
159 let req = test::TestRequest::get()
160 .uri("/networks/stellar:testnet")
161 .to_request();
162 let resp = test::call_service(&app, req).await;
163 assert_ne!(
164 resp.status(),
165 StatusCode::NOT_FOUND,
166 "GET /networks/stellar:testnet route should handle colon in path"
167 );
168 }
169
170 #[actix_web::test]
171 async fn test_patch_network_route_accepts_json() {
172 let app_state = create_mock_app_state(None, None, None, None, None, None).await;
173 let app = test::init_service(
174 App::new()
175 .app_data(web::Data::new(app_state))
176 .configure(init),
177 )
178 .await;
179
180 let req = test::TestRequest::patch()
182 .uri("/networks/evm:sepolia")
183 .set_json(serde_json::json!({
184 "rpc_urls": ["https://rpc1.example.com", "https://rpc2.example.com"]
185 }))
186 .to_request();
187 let resp = test::call_service(&app, req).await;
188 assert_ne!(
189 resp.status(),
190 StatusCode::NOT_FOUND,
191 "PATCH /networks/{{network_id}} with JSON body route not registered"
192 );
193 }
194
195 #[actix_web::test]
196 async fn test_patch_network_route_accepts_weighted_rpc_urls() {
197 let app_state = create_mock_app_state(None, None, None, None, None, None).await;
198 let app = test::init_service(
199 App::new()
200 .app_data(web::Data::new(app_state))
201 .configure(init),
202 )
203 .await;
204
205 let req = test::TestRequest::patch()
207 .uri("/networks/evm:sepolia")
208 .set_json(serde_json::json!({
209 "rpc_urls": [
210 {"url": "https://primary.example.com", "weight": 80},
211 {"url": "https://backup.example.com", "weight": 20}
212 ]
213 }))
214 .to_request();
215 let resp = test::call_service(&app, req).await;
216 assert_ne!(
217 resp.status(),
218 StatusCode::NOT_FOUND,
219 "PATCH /networks/{{network_id}} with weighted RPC URLs route not registered"
220 );
221 }
222
223 #[actix_web::test]
224 async fn test_patch_network_route_accepts_mixed_rpc_url_formats() {
225 let app_state = create_mock_app_state(None, None, None, None, None, None).await;
226 let app = test::init_service(
227 App::new()
228 .app_data(web::Data::new(app_state))
229 .configure(init),
230 )
231 .await;
232
233 let req = test::TestRequest::patch()
235 .uri("/networks/evm:sepolia")
236 .set_json(serde_json::json!({
237 "rpc_urls": [
238 "https://simple.example.com",
239 {"url": "https://weighted.example.com", "weight": 50}
240 ]
241 }))
242 .to_request();
243 let resp = test::call_service(&app, req).await;
244 assert_ne!(
245 resp.status(),
246 StatusCode::NOT_FOUND,
247 "PATCH /networks/{{network_id}} with mixed RPC URL formats route not registered"
248 );
249 }
250}