use axum::{ routing::{get, post}, Router, Json, extract::{Path, State}, }; use validator::Validate; use std::sync::Arc; use chrono::Utc; use serde::Serialize; use crate::blockchain::NacClient; use crate::error::ApiError; use crate::models::{CreateOrderRequest, OrderResponse, MarketDataResponse}; #[derive(Clone)] pub struct ExchangeState { pub client: Arc, } pub fn routes(client: Arc) -> Router { let state = ExchangeState { client }; Router::new() .route("/assets", get(get_assets)) .route("/orders", post(create_order)) .route("/orders/:order_id", get(get_order)) .route("/market/:asset", get(get_market_data)) .route("/orderbook/:asset", get(get_orderbook)) .route("/trades", get(get_trades)) .with_state(state) } #[derive(Serialize)] struct Asset { id: String, name: String, symbol: String, price: String, volume_24h: String, change_24h: String, } async fn get_assets( State(_state): State, ) -> Result>, ApiError> { // TODO: 从RWA交易所合约获取资产列表 Ok(Json(vec![ Asset { id: "asset1".to_string(), name: "房产Token A".to_string(), symbol: "RWA-A".to_string(), price: "1000.00".to_string(), volume_24h: "50000.00".to_string(), change_24h: "+2.5%".to_string(), }, Asset { id: "asset2".to_string(), name: "艺术品Token B".to_string(), symbol: "RWA-B".to_string(), price: "500.00".to_string(), volume_24h: "30000.00".to_string(), change_24h: "-1.2%".to_string(), }, ])) } async fn create_order( State(_state): State, Json(req): Json, ) -> Result, ApiError> { // 验证请求参数 req.validate() .map_err(|e: validator::ValidationErrors| ApiError::ValidationError(e.to_string()))?; // 生成订单ID let order_id = uuid::Uuid::new_v4().to_string(); // TODO: 实际应该调用RWA交易所合约创建订单 Ok(Json(OrderResponse { order_id, asset: req.asset, amount: req.amount, price: req.price, order_type: req.order_type, status: "pending".to_string(), created_at: Utc::now().timestamp(), })) } async fn get_order( State(_state): State, Path(order_id): Path, ) -> Result, ApiError> { // 验证订单ID if order_id.is_empty() { return Err(ApiError::ValidationError("Invalid order ID".to_string())); } // TODO: 从区块链或数据库获取订单详情 Ok(Json(OrderResponse { order_id, asset: "XTZH".to_string(), amount: "100.00".to_string(), price: "1.00".to_string(), order_type: "buy".to_string(), status: "filled".to_string(), created_at: Utc::now().timestamp(), })) } async fn get_market_data( State(_state): State, Path(asset): Path, ) -> Result, ApiError> { // 验证资产符号 if asset.is_empty() { return Err(ApiError::ValidationError("Invalid asset symbol".to_string())); } // TODO: 从区块链或价格预言机获取市场数据 Ok(Json(MarketDataResponse { asset, price: "1.00".to_string(), volume_24h: "1000000.00".to_string(), change_24h: "+2.5%".to_string(), high_24h: "1.05".to_string(), low_24h: "0.95".to_string(), })) } #[derive(Serialize)] struct OrderbookResponse { asset: String, bids: Vec, asks: Vec, } #[derive(Serialize)] struct OrderLevel { price: String, amount: String, total: String, } async fn get_orderbook( State(_state): State, Path(asset): Path, ) -> Result, ApiError> { // 验证资产符号 if asset.is_empty() { return Err(ApiError::ValidationError("Invalid asset symbol".to_string())); } // TODO: 从RWA交易所合约获取订单簿 Ok(Json(OrderbookResponse { asset, bids: vec![ OrderLevel { price: "0.99".to_string(), amount: "1000.00".to_string(), total: "990.00".to_string(), }, OrderLevel { price: "0.98".to_string(), amount: "2000.00".to_string(), total: "1960.00".to_string(), }, ], asks: vec![ OrderLevel { price: "1.01".to_string(), amount: "1500.00".to_string(), total: "1515.00".to_string(), }, OrderLevel { price: "1.02".to_string(), amount: "2500.00".to_string(), total: "2550.00".to_string(), }, ], })) } #[derive(Serialize)] struct Trade { id: String, asset: String, price: String, amount: String, timestamp: i64, trade_type: String, } async fn get_trades( State(_state): State, ) -> Result>, ApiError> { // TODO: 从RWA交易所合约获取最近交易 Ok(Json(vec![ Trade { id: uuid::Uuid::new_v4().to_string(), asset: "RWA-A".to_string(), price: "1000.00".to_string(), amount: "5.00".to_string(), timestamp: Utc::now().timestamp(), trade_type: "buy".to_string(), }, ])) } #[cfg(test)] mod tests { use super::*; #[test] fn test_exchange_state_creation() { let client = Arc::new(NacClient::new("http://localhost:8545".to_string())); let state = ExchangeState { client }; // 验证state创建成功 assert!(Arc::strong_count(&state.client) >= 1); } }