main.py.111 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. from fastapi import FastAPI
  2. from fastapi.middleware.cors import CORSMiddleware
  3. from dotenv import load_dotenv
  4. import os
  5. load_dotenv() # 加载 .env
  6. app = FastAPI(title="Hyperliquid DEX Backend")
  7. # 添加 CORS(允许前端访问)
  8. app.add_middleware(
  9. CORSMiddleware,
  10. allow_origins=["http://localhost:5173", "http://101.32.51.95:5173"], # 前端 URL
  11. allow_credentials=True,
  12. allow_methods=["*"],
  13. allow_headers=["*"],
  14. )
  15. @app.get("/")
  16. def read_root():
  17. return {"message": "Hyperliquid DEX Backend 就绪!"}
  18. @app.get("/health")
  19. def health_check():
  20. return {"status": "OK", "builder_address": os.getenv("BUILDER_ADDRESS")}
  21. from hyperliquid.exchange import Exchange
  22. from hyperliquid.utils import constants
  23. from hyperliquid.utils.signing import get_timestamp_ms
  24. from eth_account import Account
  25. import json
  26. TESTNET_API_URL = constants.TESTNET_API_URL
  27. info = None # 全局 Info
  28. exchange = None # 全局 Exchange
  29. @app.on_event("startup")
  30. async def startup_event():
  31. global info, exchange
  32. info = Info(TESTNET_API_URL, skip_ws=False)
  33. # 初始化 Exchange,用你的私钥(代理钱包)
  34. private_key = os.getenv("PRIVATE_KEY")
  35. account = Account.from_key(private_key)
  36. wallet_address = account.address
  37. exchange = Exchange(TESTNET_API_URL, account=account, skip_ws=True)
  38. @app.post("/approve-builder")
  39. async def approve_builder(user_address: str, max_fee_rate: int = 50):
  40. """
  41. 用户批准 Builder Fee:签名批准你的地址的最大费率。
  42. 前端调用:POST { "user_address": "0xUserAddress" }
  43. """
  44. try:
  45. # 构建批准消息(Hyperliquid Builder Fee 批准格式)
  46. timestamp = get_timestamp_ms()
  47. action = {
  48. "type": "BuilderApprove",
  49. "builder": os.getenv("BUILDER_ADDRESS"),
  50. "maxBuilderFeeBps": max_fee_rate * 10, # 0.05% = 50 * 10 = 500 bps
  51. "nonce": timestamp,
  52. }
  53. # 用户签名消息(前端提供签名,此处模拟代理)
  54. # 实际:前端用 Wagmi 签名,传签名到后端验证
  55. signed_action = exchange.sign_action(action, user_address) # 需调整为用户签名
  56. # 调用 SDK 提交批准
  57. result = exchange.builder_approve(signed_action)
  58. return {"status": "批准成功", "result": result, "fee_rate": max_fee_rate}
  59. except Exception as e:
  60. return {"error": str(e)}
  61. # 测试查询价格(从阶段 1 复用)
  62. @app.get("/prices")
  63. def get_prices():
  64. global info
  65. mids = info.all_mids()
  66. return {"prices": mids}
  67. if __name__ == "__main__":
  68. import uvicorn
  69. uvicorn.run(app, host="0.0.0.0", port=8000)