import enum from datetime import datetime from decimal import Decimal from sqlalchemy import ( Column, String, BigInteger, Integer, Numeric, DateTime, Enum, Index, JSON, ForeignKey, Boolean, Text, ) from sqlalchemy.orm import declarative_base Base = declarative_base() class LedgerEntryType(str, enum.Enum): """复式记账操作类型""" DEPOSIT = "DEPOSIT" # 链上充值 WITHDRAW = "WITHDRAW" # 提现 TRADE_BUY = "TRADE_BUY" # 现货/曲线买入扣保证金 TRADE_SELL = "TRADE_SELL" # 现货/曲线卖出增保证金 FEE_PROTOCOL = "FEE_PROTOCOL" # 协议手续费扣除 FEE_CREATOR_REBATE = "FEE_CREATOR_REBATE" # 建盘者返佣 ORDER_FREEZE = "ORDER_FREEZE" # 挂单冻结 ORDER_UNFREEZE = "ORDER_UNFREEZE" # 撤单解冻 SETTLEMENT_PAYOUT = "SETTLEMENT_PAYOUT" # 最终获胜兑付 class MarketStatus(str, enum.Enum): ACTIVE = "ACTIVE" RESOLVED = "RESOLVED" FINALISED = "FINALISED" PAUSED = "PAUSED" class UserModel(Base): """用户基础表""" __tablename__ = "users" address = Column(String(42), primary_key=True, index=True) # Checksum EVM Address created_at = Column(DateTime, default=datetime.utcnow, nullable=False) last_login_at = Column(DateTime, default=datetime.utcnow, nullable=False) is_active = Column(Boolean, default=True, nullable=False) class AccountBalanceModel(Base): """账户资金总览表 (由 Ledger 聚合维护)""" __tablename__ = "account_balances" address = Column(String(42), primary_key=True, index=True) collateral_symbol = Column(String(16), primary_key=True, default="WUSD") available_balance = Column(Numeric(precision=36, scale=18), default=Decimal("0"), nullable=False) frozen_balance = Column(Numeric(precision=36, scale=18), default=Decimal("0"), nullable=False) updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False) class LedgerEntryModel(Base): """ 不可变复式记账明细表 (Immutable Ledger) 资金流转与状态变更的唯一法定事实源 """ __tablename__ = "ledger_entries" id = Column(BigInteger().with_variant(Integer, "sqlite"), primary_key=True, autoincrement=True) tx_hash = Column(String(66), nullable=True, index=True) chain_id = Column(BigInteger, default=46630, nullable=False) user_address = Column(String(42), nullable=False, index=True) entry_type = Column(Enum(LedgerEntryType), nullable=False, index=True) amount = Column(Numeric(precision=36, scale=18), nullable=False) # 变动金额 (+ / -) balance_after = Column(Numeric(precision=36, scale=18), nullable=False) # 变动后可用余额 frozen_after = Column(Numeric(precision=36, scale=18), nullable=False) # 变动后冻结金额 related_market = Column(String(42), nullable=True, index=True) related_order_id = Column(String(64), nullable=True, index=True) extra_metadata = Column(JSON, default=dict) created_at = Column(DateTime, default=datetime.utcnow, nullable=False, index=True) __table_args__ = ( Index("idx_ledger_user_created", "user_address", "created_at"), ) class MarketModel(Base): """预测市场主表""" __tablename__ = "markets" market_address = Column(String(42), primary_key=True) question_id = Column(String(66), unique=True, nullable=False, index=True) title = Column(String(512), nullable=False) description = Column(Text, nullable=True) category = Column(String(64), default="Crypto", nullable=False, index=True) tier = Column(BigInteger, default=1, nullable=False) creator = Column(String(42), nullable=False, index=True) curve_address = Column(String(42), nullable=False) collateral_address = Column(String(42), nullable=False) fee_rate = Column(Numeric(precision=36, scale=18), default=Decimal("0.006"), nullable=False) resolution_time = Column(DateTime, nullable=False) outcomes = Column(JSON, nullable=False) # e.g. ["YES", "NO"] num_outcomes = Column(BigInteger, default=2, nullable=False) status = Column(Enum(MarketStatus), default=MarketStatus.ACTIVE, nullable=False, index=True) winning_outcome = Column(BigInteger, nullable=True) created_at_block = Column(BigInteger, nullable=False) created_at = Column(DateTime, default=datetime.utcnow, nullable=False) class OrderModel(Base): """链下/链上委托订单明细""" __tablename__ = "orders" order_id = Column(String(64), primary_key=True) market_address = Column(String(42), ForeignKey("markets.market_address"), nullable=False, index=True) user_address = Column(String(42), nullable=False, index=True) side = Column(String(8), nullable=False) # "BUY" | "SELL" outcome_index = Column(BigInteger, nullable=False) amount = Column(Numeric(precision=36, scale=18), nullable=False) # WUSD 或 Token 数量 price = Column(Numeric(precision=36, scale=18), nullable=True) # 限价 (若为市价则为空) status = Column(String(16), default="FILLED", nullable=False) # PENDING, FILLED, CANCELLED filled_amount = Column(Numeric(precision=36, scale=18), default=Decimal("0"), nullable=False) fee = Column(Numeric(precision=36, scale=18), default=Decimal("0"), nullable=False) tx_hash = Column(String(66), nullable=True) created_at = Column(DateTime, default=datetime.utcnow, nullable=False)