1use crate::market::VenueRegistry;
6use axum::Json;
7use axum::http::StatusCode;
8use axum::response::IntoResponse;
9
10pub async fn handle() -> impl IntoResponse {
12 let registry = match VenueRegistry::load() {
13 Ok(r) => r,
14 Err(e) => {
15 return (
16 StatusCode::INTERNAL_SERVER_ERROR,
17 Json(serde_json::json!({ "error": format!("Failed to load venue registry: {e}") })),
18 )
19 .into_response();
20 }
21 };
22
23 let venues: Vec<serde_json::Value> = registry
24 .list()
25 .iter()
26 .filter_map(|id| {
27 registry.get(id).map(|desc| {
28 serde_json::json!({
29 "id": desc.id,
30 "name": desc.name,
31 "base_url": desc.base_url,
32 "capabilities": desc.capability_names(),
33 })
34 })
35 })
36 .collect();
37
38 let output = serde_json::json!({
39 "venues": venues,
40 "total": registry.len(),
41 "user_venues_dir": VenueRegistry::user_venues_dir().display().to_string(),
42 });
43
44 Json(output).into_response()
45}
46
47#[cfg(test)]
48mod tests {
49 use super::*;
50 use axum::response::IntoResponse;
51
52 #[tokio::test]
53 async fn test_handle_venues() {
54 let response = handle().await.into_response();
55 let status = response.status();
56 assert!(status.is_success());
57 }
58
59 #[tokio::test]
60 async fn test_handle_venues_returns_all_built_in() {
61 let response = handle().await.into_response();
62 let status = response.status();
63 assert!(status.is_success());
64
65 let body = axum::body::to_bytes(response.into_body(), 1024 * 1024)
67 .await
68 .unwrap();
69 let json: serde_json::Value = serde_json::from_slice(&body).unwrap();
70 assert!(json["total"].as_u64().unwrap() >= 11);
71 assert!(json["venues"].is_array());
72 let venues = json["venues"].as_array().unwrap();
73 assert!(venues.iter().any(|v| v["id"] == "binance"));
74 assert!(venues.iter().any(|v| v["id"] == "kraken"));
75 for venue in venues {
77 assert!(venue["id"].is_string());
78 assert!(venue["name"].is_string());
79 assert!(venue["base_url"].is_string());
80 assert!(venue["capabilities"].is_array());
81 }
82 }
83
84 #[tokio::test]
85 async fn test_handle_venues_response_structure() {
86 let response = handle().await.into_response();
87 assert!(response.status().is_success());
88 let body = axum::body::to_bytes(response.into_body(), 1024 * 1024)
89 .await
90 .unwrap();
91 let json: serde_json::Value = serde_json::from_slice(&body).unwrap();
92 assert!(json["total"].as_u64().unwrap() >= 11);
93 let venues = json["venues"].as_array().unwrap();
94 for v in venues {
95 assert!(v["id"].is_string());
96 assert!(v["name"].is_string());
97 assert!(v["capabilities"].is_array());
98 }
99 assert!(json["user_venues_dir"].is_string());
100 }
101}