NAC_Blockchain/nac-api-server/src/exchange.rs

223 lines
5.9 KiB
Rust

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<NacClient>,
}
pub fn routes(client: Arc<NacClient>) -> 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<ExchangeState>,
) -> Result<Json<Vec<Asset>>, 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<ExchangeState>,
Json(req): Json<CreateOrderRequest>,
) -> Result<Json<OrderResponse>, 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<ExchangeState>,
Path(order_id): Path<String>,
) -> Result<Json<OrderResponse>, 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<ExchangeState>,
Path(asset): Path<String>,
) -> Result<Json<MarketDataResponse>, 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<OrderLevel>,
asks: Vec<OrderLevel>,
}
#[derive(Serialize)]
struct OrderLevel {
price: String,
amount: String,
total: String,
}
async fn get_orderbook(
State(_state): State<ExchangeState>,
Path(asset): Path<String>,
) -> Result<Json<OrderbookResponse>, 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<ExchangeState>,
) -> Result<Json<Vec<Trade>>, 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);
}
}