按显卡世代和创世编号结算回本,机房批量接入需审核网段并用硬件指纹防克隆。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-10-11 00:30:46 +08:00
parent 7d29be8b17
commit 0740016ad8
22 changed files with 1554 additions and 96 deletions
+75 -1
View File
@@ -8,7 +8,7 @@ from typing import Annotated
from pydantic import BaseModel, ConfigDict, Field, PlainSerializer
from app.models import NodeStatus, OrderStatus, TaskStatus, UserRole, WithdrawalStatus, YieldStatus
from app.models import DatacenterStatus, NodeStatus, OrderStatus, TaskStatus, UserRole, 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:_-]+$")]
@@ -73,6 +73,9 @@ class NodeOut(APIModel):
id: int
user_id: int
sn: str
node_index: int = 0
display_node_id: int = 0
genesis: bool = False
purchase_amount: MoneyText
license_months: int
licensed_at: datetime
@@ -80,6 +83,18 @@ class NodeOut(APIModel):
status: NodeStatus
last_heartbeat_at: datetime | None
callback_url: str | None
gpu_model: str | None = None
vram_gb: float | None = None
cpu_count: int | None = None
memory_gb: float | None = None
hardware_weight: float = 0.05
gpu_generation: str = "10"
recovery_days: int = 540
generation_locked: bool = False
recoverable_stake_amount: MoneyText | None = None
is_whitelist: bool = False
client_ip: str | None = None
hardware_fingerprint: str | None = None
class NodeView(NodeOut):
@@ -93,13 +108,23 @@ class NodeView(NodeOut):
class HeartbeatIn(APIModel):
sn: SN
token: str | None = Field(default=None, max_length=128)
gpu_model: str | None = Field(default=None, max_length=128)
vram_gb: float | None = Field(default=None, ge=0, le=1024)
cpu_count: int | None = Field(default=None, ge=1, le=1024)
memory_gb: float | None = Field(default=None, ge=0, le=4096)
hardware_fingerprint: str | None = Field(default=None, max_length=64, pattern=r"^[a-fA-F0-9]{64}$")
class HeartbeatOut(APIModel):
sn: str
display_node_id: int = 0
status: NodeStatus
last_heartbeat_at: datetime
server_time: datetime
hardware_weight: float = 0.05
gpu_generation: str = "10"
recovery_days: int = 540
recoverable_stake_amount: MoneyText | None = None
class TaskOut(APIModel):
@@ -198,6 +223,7 @@ class OrderOut(APIModel):
created_at: datetime
reviewed_at: datetime | None = None
sn: str | None = None
display_node_id: int | None = None
class OrderView(OrderOut):
@@ -253,6 +279,54 @@ class DashboardOut(APIModel):
today_points: MoneyText
license_price: MoneyText
license_asset: str
network_nodes: int = 0
network_online: int = 0
nodes: list[NodeView]
orders: list[OrderOut]
withdrawals: list[WithdrawalOut]
datacenter_applications: list[DatacenterOut] = []
class WhitelistToggle(APIModel):
is_whitelist: bool
class IPWhitelistCreate(APIModel):
ip_address: str = Field(min_length=3, max_length=64)
note: str | None = Field(default=None, max_length=128)
class IPWhitelistOut(APIModel):
id: int
ip_address: str
note: str | None = None
created_at: datetime
class DatacenterApply(APIModel):
contact: str = Field(min_length=4, max_length=128)
node_count: int = Field(ge=1, le=10000)
subnet_ip: str = Field(min_length=3, max_length=64)
hardware_proof: str = Field(min_length=4, max_length=2000)
gpu_generation: str = Field(pattern=r"^(10|30|40)$")
class DatacenterOut(APIModel):
id: int
user_id: int
contact: str
node_count: int
subnet_ip: str
hardware_proof: str
gpu_generation: str
status: DatacenterStatus
note: str | None = None
created_at: datetime
reviewed_at: datetime | None = None
class DatacenterView(DatacenterOut):
wallet_address: str
DashboardOut.model_rebuild()