📦 Code Changes: View Diff
Programmatic traders need API documentation to integrate with our exchange. Instead of maintaining separate docs that drift from code, we auto-generate OpenAPI 3.0 spec directly from Rust types.
- Serve interactive API docs at
/docs(Swagger UI) - Export
openapi.jsonfor SDK generation - Keep docs in sync with code (single source of truth)
| Term | Definition |
|---|---|
| OpenAPI | Industry-standard API specification format (formerly Swagger) |
| utoipa | Rust crate for compile-time OpenAPI generation |
| Swagger UI | Interactive API documentation interface |
| Code-First | Generate spec from code, not YAML files |
┌─────────── OpenAPI Integration Flow ────────────┐
│ │
│ Rust Handlers ──▶ #[utoipa::path] ──▶ OpenAPI │
│ │ │ │
│ │ ▼ │
│ │ Swagger UI │
│ │ (/docs) │
│ │ │ │
│ ▼ ▼ │
│ Type-Safe API ◀─────────────────▶ openapi.json │
│ │ │
│ ▼ │
│ SDK Clients │
│ (Python, TS) │
└─────────────────────────────────────────────────┘
Cargo.toml:
[dependencies]
+ utoipa = { version = "5.3", features = ["axum_extras", "chrono", "uuid"] }
+ utoipa-swagger-ui = { version = "8.0", features = ["axum"] }Create src/gateway/openapi.rs:
use utoipa::OpenApi;
#[derive(OpenApi)]
#[openapi(
info(
title = "Zero X Infinity Exchange API",
version = "1.0.0",
description = "High-performance crypto exchange API (1.3M orders/sec)"
),
paths(
handlers::health_check,
handlers::get_depth,
handlers::get_klines,
// ... all API handlers
),
components(schemas(
types::ApiResponse<()>,
types::DepthApiData,
// ... all response types
))
)]
pub struct ApiDoc;Add #[utoipa::path] to each handler:
+ #[utoipa::path(
+ get,
+ path = "/api/v1/public/depth",
+ params(
+ ("symbol" = String, Query, description = "Trading pair"),
+ ("limit" = Option<u32>, Query, description = "Depth levels")
+ ),
+ responses(
+ (status = 200, description = "Order book depth", body = ApiResponse<DepthApiData>)
+ ),
+ tag = "Market Data"
+ )]
pub async fn get_depth(
State(state): State<Arc<AppState>>,
Query(params): Query<HashMap<String, String>>,
) -> impl IntoResponse {
// ... existing implementation ...
}Add ToSchema to response types:
+ use utoipa::ToSchema;
- #[derive(Serialize, Deserialize)]
+ #[derive(Serialize, Deserialize, ToSchema)]
pub struct DepthApiData {
+ #[schema(example = "BTC_USDT")]
pub symbol: String,
+ #[schema(example = json!([["85000.00", "0.5"]]))]
pub bids: Vec<[String; 2]>,
+ #[schema(example = json!([["85001.00", "0.3"]]))]
pub asks: Vec<[String; 2]>,
}In src/gateway/mod.rs:
+ use utoipa_swagger_ui::SwaggerUi;
+ use crate::gateway::openapi::ApiDoc;
let app = Router::new()
.route("/api/v1/health", get(handlers::health_check))
.nest("/api/v1/public", public_routes)
.nest("/api/v1/private", private_routes)
+ .merge(
+ SwaggerUi::new("/docs")
+ .url("/api-docs/openapi.json", ApiDoc::openapi())
+ )
.with_state(state);| Endpoint | Method | Description |
|---|---|---|
/api/v1/health |
GET | Health check |
/api/v1/public/depth |
GET | Order book depth |
/api/v1/public/klines |
GET | K-line data |
/api/v1/public/assets |
GET | Asset list |
/api/v1/public/symbols |
GET | Trading pairs |
/api/v1/public/exchange_info |
GET | Exchange metadata |
| Endpoint | Method | Description |
|---|---|---|
/api/v1/private/order |
POST | Create order |
/api/v1/private/cancel |
POST | Cancel order |
/api/v1/private/orders |
GET | Query orders |
/api/v1/private/trades |
GET | Trade history |
/api/v1/private/balances |
GET | Balance query |
/api/v1/private/balances/all |
GET | All balances |
/api/v1/private/transfer |
POST | Internal transfer |
/api/v1/private/transfer/{id} |
GET | Transfer status |
Auto-generated Python client with Ed25519 signing:
from zero_x_infinity_sdk import ZeroXInfinityClient
client = ZeroXInfinityClient(
api_key="your_api_key",
secret_key_bytes=secret_key # Ed25519 private key
)
# Create order
order = client.create_order(
symbol="BTC_USDT",
side="BUY",
price="85000.00",
qty="0.001"
)import { ZeroXInfinityClient } from './zero_x_infinity_sdk';
const client = new ZeroXInfinityClient(apiKey, secretKey);
const depth = await client.getDepth('BTC_USDT');cargo run --release -- --gateway --port 8080
# Open: http://localhost:8080/docs| Test Category | Tests | Result |
|---|---|---|
| Unit Tests | 293 | ✅ All pass |
| Public Endpoints | 6 | ✅ All pass |
| Private Endpoints | 9 | ✅ All pass |
| E2E Total | 17 | ✅ All pass |
In this chapter, we added OpenAPI documentation to our trading engine:
| Achievement | Result |
|---|---|
| Swagger UI | Available at /docs |
| OpenAPI Spec | 15 endpoints documented |
| Python SDK | Auto-generated with Ed25519 |
| TypeScript SDK | Type-safe client |
| Zero Breaking Changes | All existing tests pass |
Next Chapter: With resilience (0x0D) and documentation (0x0E) complete, the foundation is solid. The next logical step is 0x0F: Deposit & Withdraw—connecting to blockchain for real crypto funding.
📦 代码变更: 查看 Diff
程序化交易者需要 API 文档。与其手写 YAML 文档(容易和代码不同步),不如直接从 Rust 类型生成 OpenAPI 3.0 规范。
- 在
/docs提供交互式文档(Swagger UI) - 导出
openapi.json用于 SDK 生成 - 文档和代码保持同步(单一事实来源)
| 术语 | 定义 |
|---|---|
| OpenAPI | 行业标准的 API 规范格式(前身是 Swagger) |
| utoipa | Rust 编译时 OpenAPI 生成库 |
| Swagger UI | 交互式 API 文档界面 |
| 代码优先 | 从代码生成规范,而非 YAML 文件 |
┌─────────── OpenAPI 集成流程 ────────────┐
│ │
│ Rust Handlers ──▶ #[utoipa::path] ──▶ OpenAPI
│ │ │
│ │ ▼
│ │ Swagger UI
│ │ (/docs)
│ ▼ │
│ 类型安全 API ◀────────────────▶ openapi.json
│ │
│ ▼
│ SDK 客户端
│ (Python, TS)
└──────────────────────────────────────────┘
Cargo.toml:
[dependencies]
+ utoipa = { version = "5.3", features = ["axum_extras", "chrono", "uuid"] }
+ utoipa-swagger-ui = { version = "8.0", features = ["axum"] }创建 src/gateway/openapi.rs:
use utoipa::OpenApi;
#[derive(OpenApi)]
#[openapi(
info(
title = "Zero X Infinity Exchange API",
version = "1.0.0",
description = "高性能加密货币交易所 API (1.3M 订单/秒)"
),
paths(
handlers::health_check,
handlers::get_depth,
handlers::get_klines,
// ... 所有 API handlers
),
components(schemas(
types::ApiResponse<()>,
types::DepthApiData,
// ... 所有响应类型
))
)]
pub struct ApiDoc;为每个 handler 添加 #[utoipa::path]:
+ #[utoipa::path(
+ get,
+ path = "/api/v1/public/depth",
+ params(
+ ("symbol" = String, Query, description = "交易对"),
+ ("limit" = Option<u32>, Query, description = "深度层数")
+ ),
+ responses(
+ (status = 200, description = "订单簿深度", body = ApiResponse<DepthApiData>)
+ ),
+ tag = "行情数据"
+ )]
pub async fn get_depth(
State(state): State<Arc<AppState>>,
Query(params): Query<HashMap<String, String>>,
) -> impl IntoResponse {
// ... 现有实现 ...
}为响应类型添加 ToSchema:
+ use utoipa::ToSchema;
- #[derive(Serialize, Deserialize)]
+ #[derive(Serialize, Deserialize, ToSchema)]
pub struct DepthApiData {
+ #[schema(example = "BTC_USDT")]
pub symbol: String,
+ #[schema(example = json!([["85000.00", "0.5"]]))]
pub bids: Vec<[String; 2]>,
+ #[schema(example = json!([["85001.00", "0.3"]]))]
pub asks: Vec<[String; 2]>,
}在 src/gateway/mod.rs 中:
+ use utoipa_swagger_ui::SwaggerUi;
+ use crate::gateway::openapi::ApiDoc;
let app = Router::new()
.route("/api/v1/health", get(handlers::health_check))
.nest("/api/v1/public", public_routes)
.nest("/api/v1/private", private_routes)
+ .merge(
+ SwaggerUi::new("/docs")
+ .url("/api-docs/openapi.json", ApiDoc::openapi())
+ )
.with_state(state);| 端点 | 方法 | 描述 |
|---|---|---|
/api/v1/health |
GET | 健康检查 |
/api/v1/public/depth |
GET | 订单簿深度 |
/api/v1/public/klines |
GET | K 线数据 |
/api/v1/public/assets |
GET | 资产列表 |
/api/v1/public/symbols |
GET | 交易对 |
/api/v1/public/exchange_info |
GET | 交易所信息 |
| 端点 | 方法 | 描述 |
|---|---|---|
/api/v1/private/order |
POST | 创建订单 |
/api/v1/private/cancel |
POST | 取消订单 |
/api/v1/private/orders |
GET | 查询订单 |
/api/v1/private/trades |
GET | 成交历史 |
/api/v1/private/balances |
GET | 余额查询 |
/api/v1/private/balances/all |
GET | 所有余额 |
/api/v1/private/transfer |
POST | 内部划转 |
/api/v1/private/transfer/{id} |
GET | 划转状态 |
自动生成的 Python 客户端(含 Ed25519 签名):
from zero_x_infinity_sdk import ZeroXInfinityClient
client = ZeroXInfinityClient(
api_key="your_api_key",
secret_key_bytes=secret_key # Ed25519 私钥
)
# 创建订单
order = client.create_order(
symbol="BTC_USDT",
side="BUY",
price="85000.00",
qty="0.001"
)import { ZeroXInfinityClient } from './zero_x_infinity_sdk';
const client = new ZeroXInfinityClient(apiKey, secretKey);
const depth = await client.getDepth('BTC_USDT');cargo run --release -- --gateway --port 8080
# 打开: http://localhost:8080/docs| 测试类别 | 数量 | 结果 |
|---|---|---|
| 单元测试 | 293 | ✅ 全部通过 |
| 公开端点 | 6 | ✅ 全部通过 |
| 私有端点 | 9 | ✅ 全部通过 |
| E2E 总计 | 17 | ✅ 全部通过 |
本章我们为交易引擎添加了 OpenAPI 文档:
| 成就 | 结果 |
|---|---|
| Swagger UI | 可通过 /docs 访问 |
| OpenAPI 规范 | 15 个端点已文档化 |
| Python SDK | 自动生成(含 Ed25519) |
| TypeScript SDK | 类型安全的客户端 |
| 零破坏性变更 | 所有现有测试通过 |
下一章:随着鲁棒性(0x0D)和文档化(0x0E)的完成,基础已经稳固。下一个合理的步骤是 0x0F: 充值与提现 —— 连接区块链实现真正的加密货币资金。