Skip to main content

scope/web/api/
venues.rs

1//! Venue listing API handler.
2//!
3//! GET /api/venues — Returns available exchange venues and their capabilities.
4
5use crate::market::VenueRegistry;
6use axum::Json;
7use axum::http::StatusCode;
8use axum::response::IntoResponse;
9
10/// GET /api/venues — List available exchange venues.
11pub 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}