153 lines
5.4 KiB
Python
153 lines
5.4 KiB
Python
from fastapi import APIRouter, Depends, HTTPException
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
from typing import List, Optional
|
|
from app.api.dependencies import get_db_session, get_current_user, create_access_token
|
|
from app.schemas.dtos import (
|
|
UserAuthRequest,
|
|
TokenResponse,
|
|
AccountBalanceDTO,
|
|
LedgerEntryDTO,
|
|
CreateMarketMetadataRequest,
|
|
ResolveMarketRequest,
|
|
MarketDTO,
|
|
CreateOrderRequest,
|
|
OrderDTO
|
|
)
|
|
from app.domains.ledger.service import LedgerService
|
|
from app.domains.trading.service import MarketService, TradingService
|
|
|
|
api_router = APIRouter(prefix="/v1")
|
|
|
|
# ================= Auth Routes =================
|
|
@api_router.post("/auth/login", response_model=TokenResponse)
|
|
async def login_with_wallet(req: UserAuthRequest, session: AsyncSession = Depends(get_db_session)):
|
|
"""Web3 SIWE 钱包快速认证"""
|
|
token = create_access_token(req.address)
|
|
return TokenResponse(access_token=token, address=req.address.lower())
|
|
|
|
# ================= Market Routes =================
|
|
@api_router.post("/markets/metadata", response_model=MarketDTO)
|
|
async def create_market_metadata(
|
|
req: CreateMarketMetadataRequest,
|
|
current_user: str = Depends(get_current_user),
|
|
session: AsyncSession = Depends(get_db_session)
|
|
):
|
|
"""保存预测市场的链下元数据 (标题, 描述, 类别, 2~255个选项)"""
|
|
market_service = MarketService(session)
|
|
market = await market_service.save_market_metadata(
|
|
market_address=req.market_address,
|
|
question_id=req.question_id,
|
|
title=req.title,
|
|
description=req.description,
|
|
category=req.category,
|
|
outcomes=req.outcomes,
|
|
resolution_time=req.resolution_time,
|
|
creator=current_user
|
|
)
|
|
return MarketDTO(
|
|
market_address=market.market_address,
|
|
question_id=market.question_id,
|
|
title=market.title,
|
|
description=market.description,
|
|
category=market.category,
|
|
tier=market.tier,
|
|
creator=market.creator,
|
|
status=market.status.value if hasattr(market.status, 'value') else str(market.status),
|
|
outcomes=market.outcomes,
|
|
winning_outcome=market.winning_outcome,
|
|
resolution_time=market.resolution_time,
|
|
created_at=market.created_at
|
|
)
|
|
|
|
@api_router.get("/markets", response_model=List[MarketDTO])
|
|
async def get_markets(
|
|
category: Optional[str] = None,
|
|
status: Optional[str] = None,
|
|
session: AsyncSession = Depends(get_db_session)
|
|
):
|
|
"""获取预测市场列表"""
|
|
market_service = MarketService(session)
|
|
markets = await market_service.list_markets(category, status)
|
|
return [
|
|
MarketDTO(
|
|
market_address=m.market_address,
|
|
question_id=m.question_id,
|
|
title=m.title,
|
|
description=m.description,
|
|
category=m.category,
|
|
tier=m.tier,
|
|
creator=m.creator,
|
|
status=m.status.value if hasattr(m.status, 'value') else str(m.status),
|
|
outcomes=m.outcomes,
|
|
winning_outcome=m.winning_outcome,
|
|
resolution_time=m.resolution_time,
|
|
created_at=m.created_at
|
|
) for m in markets
|
|
]
|
|
|
|
# ================= Orders & Trading =================
|
|
@api_router.post("/orders", response_model=OrderDTO)
|
|
async def place_order(
|
|
req: CreateOrderRequest,
|
|
current_user: str = Depends(get_current_user),
|
|
session: AsyncSession = Depends(get_db_session)
|
|
):
|
|
"""创建并执行交易委托"""
|
|
trading_service = TradingService(session)
|
|
order = await trading_service.place_order(
|
|
user_address=current_user,
|
|
market_address=req.market_address,
|
|
outcome_index=req.outcome_index,
|
|
side=req.side,
|
|
amount=req.amount,
|
|
price=req.price
|
|
)
|
|
return OrderDTO(
|
|
order_id=order.order_id,
|
|
market_address=order.market_address,
|
|
user_address=order.user_address,
|
|
side=order.side,
|
|
outcome_index=order.outcome_index,
|
|
amount=order.amount,
|
|
status=order.status,
|
|
fee=order.fee,
|
|
created_at=order.created_at
|
|
)
|
|
|
|
# ================= Ledger & Balances =================
|
|
@api_router.get("/wallet/balance", response_model=AccountBalanceDTO)
|
|
async def get_balance(
|
|
current_user: str = Depends(get_current_user),
|
|
session: AsyncSession = Depends(get_db_session)
|
|
):
|
|
"""查询用户资金与冻结余额"""
|
|
ledger_service = LedgerService(session)
|
|
bal = await ledger_service.get_or_create_balance(current_user)
|
|
return AccountBalanceDTO(
|
|
address=bal.address,
|
|
collateral_symbol=bal.collateral_symbol,
|
|
available_balance=bal.available_balance,
|
|
frozen_balance=bal.frozen_balance
|
|
)
|
|
|
|
@api_router.get("/wallet/ledger", response_model=List[LedgerEntryDTO])
|
|
async def get_ledger_history(
|
|
current_user: str = Depends(get_current_user),
|
|
limit: int = 50,
|
|
session: AsyncSession = Depends(get_db_session)
|
|
):
|
|
"""查询不可变复式记账流水"""
|
|
ledger_service = LedgerService(session)
|
|
entries = await ledger_service.list_user_ledger(current_user, limit)
|
|
return [
|
|
LedgerEntryDTO(
|
|
id=e.id,
|
|
entry_type=e.entry_type.value if hasattr(e.entry_type, 'value') else str(e.entry_type),
|
|
amount=e.amount,
|
|
balance_after=e.balance_after,
|
|
frozen_after=e.frozen_after,
|
|
related_market=e.related_market,
|
|
created_at=e.created_at
|
|
) for e in entries
|
|
]
|