初始化 HyperNode-AI 控制面。

包含节点账本、每日清算,以及 Ubuntu 交互式部署脚本。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-10-10 21:53:20 +08:00
commit 2bbdb00a4d
31 changed files with 2450 additions and 0 deletions
+156
View File
@@ -0,0 +1,156 @@
"""接口请求与响应。金额在 JSON 里用字符串,避免浮点误差。"""
from __future__ import annotations
from datetime import date, datetime
from decimal import Decimal
from typing import Annotated
from pydantic import BaseModel, ConfigDict, Field, PlainSerializer
from app.models import NodeStatus, TaskStatus, WithdrawalStatus, YieldStatus
SN = Annotated[str, Field(min_length=4, max_length=64, pattern=r"^[A-Za-z0-9_-]+$")]
WALLET = Annotated[str, Field(min_length=4, max_length=128, pattern=r"^[A-Za-z0-9:_-]+$")]
MoneyText = Annotated[Decimal, PlainSerializer(lambda value: format(value, "f"), return_type=str)]
class APIModel(BaseModel):
model_config = ConfigDict(from_attributes=True)
class UserCreate(APIModel):
wallet_address: WALLET
class UserOut(APIModel):
id: int
wallet_address: str
created_at: datetime
class NodeCreate(APIModel):
wallet_address: WALLET
sn: SN
purchase_amount: Decimal = Field(gt=0, max_digits=24, decimal_places=8)
callback_url: str | None = None
class NodeOut(APIModel):
id: int
user_id: int
sn: str
purchase_amount: MoneyText
license_months: int
licensed_at: datetime
license_expires_at: datetime
status: NodeStatus
last_heartbeat_at: datetime | None
callback_url: str | None
class HeartbeatIn(APIModel):
sn: SN
class HeartbeatOut(APIModel):
sn: str
status: NodeStatus
last_heartbeat_at: datetime
server_time: datetime
class TaskOut(APIModel):
task_id: str
task_type: str
payload: dict
status: TaskStatus
dispatched_at: datetime
deadline_at: datetime
class TaskReportIn(APIModel):
sn: SN
task_id: str = Field(min_length=36, max_length=36)
success: bool
nonce: str = Field(min_length=8, max_length=128)
class ContributionOut(APIModel):
sn: str
yield_date: date
eligible: bool
online_seconds: int
eligible_seconds: int
online_rate: MoneyText
tasks_dispatched: int
tasks_completed: int
task_response_rate: MoneyText
online_weight: MoneyText
task_weight: MoneyText
performance: MoneyText
compute_output: MoneyText
points_delta: MoneyText
cycle_days: int
class YieldOut(APIModel):
id: int
node_id: int
user_id: int
yield_date: date
compute_output: MoneyText
points_delta: MoneyText
online_seconds: int
eligible_seconds: int
online_rate: MoneyText
tasks_dispatched: int
tasks_completed: int
task_response_rate: MoneyText
online_weight: MoneyText
task_weight: MoneyText
performance: MoneyText
cycle_days: int
status: YieldStatus
is_partial: bool
created_at: datetime
class SettleOut(APIModel):
yield_date: date
created: int
skipped: int
total_points: MoneyText
is_partial: bool
class WithdrawalCreate(APIModel):
wallet_address: WALLET
amount: Decimal = Field(gt=0, max_digits=24, decimal_places=8)
asset_symbol: str = Field(default="POINT", min_length=1, max_length=32)
class WithdrawalConfirm(APIModel):
tx_hash: str = Field(min_length=6, max_length=128, pattern=r"^[A-Za-z0-9]+$")
class WithdrawalReject(APIModel):
note: str | None = Field(default=None, max_length=500)
class WithdrawalOut(APIModel):
id: int
user_id: int
amount: MoneyText
asset_symbol: str
tx_hash: str | None
status: WithdrawalStatus
note: str | None
available_after: MoneyText | None = None
created_at: datetime
updated_at: datetime
class BalanceOut(APIModel):
wallet_address: str
available_points: MoneyText