Files
tradeing/backend/app/routes/exchange_route.py
T
chpark c4e6aab7b2 React + FastAPI 풀 마이그레이션 — Streamlit 제거
- backend/ — FastAPI + JWT + 모든 REST 엔드포인트
- frontend/ — Next.js 14 + Tailwind + 7페이지 (대시보드/트레이드/거래소/자동매매/설정/내정보/로그인)
- core_logic.py — 신호계산/알림 로직 분리 (기존 app_streamlit.py 에서 추출)
- users_db.py + bcrypt 인증, exchange_keys.py + Fernet 암호화
- trades_db.py — 진입/청산 lifecycle 추적, signal_events raw 로그
- settings_db.py — 모든 운영 파라미터 DB 영속 저장 (RSI/거래량/펀딩비 임계값 포함)
- docker-compose: frontend / backend / postgres + Traefik 라우팅
- assets/logo.svg — JUNGGOMOA 그라디언트 로고

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 17:27:11 +09:00

74 lines
2.1 KiB
Python

from fastapi import APIRouter, Depends, HTTPException
from pydantic import BaseModel
from typing import Optional
import exchange_keys
import exchange_adapters
from ..auth import require_user
router = APIRouter()
class CredIn(BaseModel):
exchange: str
label: str = ""
api_key: str
api_secret: str
passphrase: Optional[str] = None
testnet: bool = False
class CredUpdateIn(BaseModel):
exchange: Optional[str] = None
label: Optional[str] = None
api_key: Optional[str] = None
api_secret: Optional[str] = None
passphrase: Optional[str] = None
testnet: Optional[bool] = None
enabled: Optional[bool] = None
def _serialize_cred(c):
d = dict(c)
for k in ["created_at", "updated_at"]:
if d.get(k) is not None:
d[k] = str(d[k])
return d
@router.get("/credentials")
def list_creds(_: dict = Depends(require_user)):
return [_serialize_cred(c) for c in exchange_keys.list_credentials()]
@router.post("/credentials")
def add_cred(body: CredIn, _: dict = Depends(require_user)):
cid = exchange_keys.add_credential(
body.exchange, body.label, body.api_key, body.api_secret,
body.passphrase, body.testnet, True,
)
if not cid:
raise HTTPException(status_code=400, detail="등록 실패")
return {"id": cid}
@router.put("/credentials/{cred_id}")
def update_cred(cred_id: int, body: CredUpdateIn, _: dict = Depends(require_user)):
fields = {k: v for k, v in body.dict().items() if v is not None}
if not fields:
raise HTTPException(status_code=400, detail="변경 항목 없음")
if not exchange_keys.update_credential(cred_id, **fields):
raise HTTPException(status_code=404, detail="not found")
return {"ok": True}
@router.delete("/credentials/{cred_id}")
def delete_cred(cred_id: int, _: dict = Depends(require_user)):
if not exchange_keys.delete_credential(cred_id):
raise HTTPException(status_code=404, detail="not found")
return {"ok": True}
@router.get("/exchanges")
def supported_exchanges(_: dict = Depends(require_user)):
return exchange_keys.SUPPORTED_EXCHANGES