generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } // ==================== 挖矿配置 ==================== // 挖矿全局配置 model MiningConfig { id String @id @default(uuid()) totalShares Decimal @db.Decimal(30, 8) // 总积分股数量 (100.02B) distributionPool Decimal @db.Decimal(30, 8) // 分配池 (200M) remainingDistribution Decimal @db.Decimal(30, 8) // 剩余可分配 halvingPeriodYears Int @default(2) // 减半周期(年) currentEra Int @default(1) // 当前纪元 eraStartDate DateTime // 当前纪元开始日期 minuteDistribution Decimal @db.Decimal(30, 18) // 每分钟分配量 isActive Boolean @default(false) // 是否已激活挖矿 activatedAt DateTime? // 激活时间 createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@map("mining_configs") } // 减半纪元记录 model MiningEra { id String @id @default(uuid()) eraNumber Int @unique startDate DateTime endDate DateTime? initialDistribution Decimal @db.Decimal(30, 8) // 纪元初始可分配量 totalDistributed Decimal @default(0) @db.Decimal(30, 8) // 已分配量 minuteDistribution Decimal @db.Decimal(30, 18) // 每分钟分配量 isActive Boolean @default(true) createdAt DateTime @default(now()) @@map("mining_eras") } // ==================== 用户挖矿账户 ==================== // 用户挖矿账户 model MiningAccount { id String @id @default(uuid()) accountSequence String @unique totalMined Decimal @default(0) @db.Decimal(30, 8) // 总挖到的积分股 availableBalance Decimal @default(0) @db.Decimal(30, 8) // 可用余额 frozenBalance Decimal @default(0) @db.Decimal(30, 8) // 冻结余额 totalContribution Decimal @default(0) @db.Decimal(30, 8) // 当前算力(从 contribution-service 同步) lastSyncedAt DateTime? // 最后同步算力时间 createdAt DateTime @default(now()) updatedAt DateTime @updatedAt records MiningRecord[] transactions MiningTransaction[] @@index([totalContribution(sort: Desc)]) @@map("mining_accounts") } // 挖矿记录(分钟级别) model MiningRecord { id String @id @default(uuid()) accountSequence String miningMinute DateTime // 挖矿分钟(精确到分钟) contributionRatio Decimal @db.Decimal(30, 18) // 当时的算力占比 totalContribution Decimal @db.Decimal(30, 8) // 当时的总算力 minuteDistribution Decimal @db.Decimal(30, 18) // 当分钟总分配量 minedAmount Decimal @db.Decimal(30, 18) // 挖到的数量 createdAt DateTime @default(now()) account MiningAccount @relation(fields: [accountSequence], references: [accountSequence]) @@unique([accountSequence, miningMinute]) @@index([miningMinute]) @@map("mining_records") } // 挖矿交易流水 model MiningTransaction { id String @id @default(uuid()) accountSequence String type String // MINE, FREEZE, UNFREEZE, TRANSFER_OUT, TRANSFER_IN, BURN amount Decimal @db.Decimal(30, 8) balanceBefore Decimal @db.Decimal(30, 8) balanceAfter Decimal @db.Decimal(30, 8) referenceId String? // 关联ID(如交易ID、划转ID) referenceType String? // 关联类型 // 交易对手方信息 counterpartyType String? @map("counterparty_type") // USER, POOL, SYSTEM counterpartyAccountSeq String? @map("counterparty_account_seq") // 对手方账户序列号 counterpartyUserId String? @map("counterparty_user_id") // 对手方用户ID // 详细备注(包含完整交易信息,格式: "划转到用户[U123456]") memo String? @db.Text description String? // 保留兼容旧字段 createdAt DateTime @default(now()) account MiningAccount @relation(fields: [accountSequence], references: [accountSequence]) @@index([accountSequence, createdAt(sort: Desc)]) @@index([type]) @@index([counterpartyAccountSeq]) @@index([counterpartyUserId]) @@map("mining_transactions") } // ==================== 挖矿统计 ==================== // 每分钟挖矿统计 model MinuteMiningStat { id String @id @default(uuid()) minute DateTime @unique totalContribution Decimal @db.Decimal(30, 8) // 参与挖矿的总算力 totalDistributed Decimal @db.Decimal(30, 18) // 该分钟分配的总量 participantCount Int // 参与者数量 burnAmount Decimal @default(0) @db.Decimal(30, 8) // 该分钟销毁量 createdAt DateTime @default(now()) @@index([minute(sort: Desc)]) @@map("minute_mining_stats") } // 每日挖矿统计 model DailyMiningStat { id String @id @default(uuid()) date DateTime @unique @db.Date totalContribution Decimal @db.Decimal(30, 8) totalDistributed Decimal @db.Decimal(30, 8) totalBurned Decimal @db.Decimal(30, 8) participantCount Int avgContributionRate Decimal @db.Decimal(10, 8) // 平均算力利用率 createdAt DateTime @default(now()) @@map("daily_mining_stats") } // ==================== 销毁机制 ==================== // 黑洞账户 model BlackHole { id String @id @default(uuid()) totalBurned Decimal @default(0) @db.Decimal(30, 8) // 已销毁总量 targetBurn Decimal @db.Decimal(30, 8) // 目标销毁量 (10B) remainingBurn Decimal @db.Decimal(30, 8) // 剩余待销毁 lastBurnMinute DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt records BurnRecord[] @@map("black_holes") } // 销毁记录 model BurnRecord { id String @id @default(uuid()) blackHoleId String burnMinute DateTime burnAmount Decimal @db.Decimal(30, 18) remainingTarget Decimal @db.Decimal(30, 8) // 销毁后剩余目标 // 来源信息(从哪个池/用户销毁) sourceType String? @map("source_type") // CIRCULATION_POOL, USER, SYSTEM sourceAccountSeq String? @map("source_account_seq") // 来源账户序列号 sourceUserId String? @map("source_user_id") // 来源用户ID // 详细备注 memo String? @db.Text createdAt DateTime @default(now()) blackHole BlackHole @relation(fields: [blackHoleId], references: [id]) @@unique([blackHoleId, burnMinute]) @@index([burnMinute]) @@index([sourceAccountSeq]) @@map("burn_records") } // ==================== 价格相关 ==================== // 价格快照(每分钟) model PriceSnapshot { id String @id @default(uuid()) snapshotTime DateTime @unique price Decimal @db.Decimal(30, 18) // 当时价格 sharePool Decimal @db.Decimal(30, 8) // 股池 blackHoleAmount Decimal @db.Decimal(30, 8) // 黑洞数量 circulationPool Decimal @db.Decimal(30, 8) // 流通池 effectiveDenominator Decimal @db.Decimal(30, 8) // 有效分母 createdAt DateTime @default(now()) @@index([snapshotTime(sort: Desc)]) @@map("price_snapshots") } // ==================== 池账户系统 ==================== // 池账户类型枚举 enum PoolAccountType { SHARE_POOL // 积分股池 - 总股池 BLACK_HOLE_POOL // 黑洞积分股池 - 销毁池 CIRCULATION_POOL // 流通积分股池 - 流通池 } // 池账户交易类型枚举 enum PoolTransactionType { // 积分股池操作 MINING_DISTRIBUTE // 挖矿分配(股池 -> 用户) FEE_COLLECT // 手续费收取(用户 -> 股池) INITIAL_INJECT // 初始注入 // 黑洞池操作 BURN // 销毁(流通池 -> 黑洞) // 流通池操作 USER_TRANSFER_IN // 用户划入(用户 -> 流通池) USER_TRANSFER_OUT // 用户划出(流通池 -> 用户) TRADE_BUY // 交易买入 TRADE_SELL // 交易卖出 // 通用操作 POOL_TRANSFER // 池间划转 ADJUSTMENT // 系统调整 } // 池账户(管理三大池:积分股池、黑洞积分股池、流通积分股池) model PoolAccount { id String @id @default(uuid()) poolType PoolAccountType @unique @map("pool_type") // 池类型 name String // 池名称 balance Decimal @default(0) @db.Decimal(30, 8) // 当前余额 totalInflow Decimal @default(0) @db.Decimal(30, 8) // 累计流入 totalOutflow Decimal @default(0) @db.Decimal(30, 8) // 累计流出 isActive Boolean @default(true) @map("is_active") description String? createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") transactions PoolTransaction[] @@index([poolType]) @@map("pool_accounts") } // 池账户交易明细(包含交易对手方信息) model PoolTransaction { id String @id @default(uuid()) poolAccountId String @map("pool_account_id") poolType PoolAccountType @map("pool_type") transactionType PoolTransactionType @map("transaction_type") // 金额信息 amount Decimal @db.Decimal(30, 8) balanceBefore Decimal @map("balance_before") @db.Decimal(30, 8) balanceAfter Decimal @map("balance_after") @db.Decimal(30, 8) // 交易对手方信息(关键:用户ID和账户序列号) counterpartyType String? @map("counterparty_type") // USER, POOL, SYSTEM, EXTERNAL counterpartyAccountSeq String? @map("counterparty_account_seq") // 对手方账户序列号 counterpartyUserId String? @map("counterparty_user_id") // 对手方用户ID counterpartyPoolType PoolAccountType? @map("counterparty_pool_type") // 如果对手方是池账户 // 关联信息 referenceId String? @map("reference_id") // 关联业务ID(如订单ID、划转ID) referenceType String? @map("reference_type") // 关联类型 txHash String? @map("tx_hash") // 链上交易哈希(如有) // 详细备注(包含完整交易信息) // 格式示例: "挖矿分配给用户[U123456], 算力占比0.5%, 分钟2024-01-10 10:30" memo String? @db.Text // 扩展数据(JSON格式存储更多业务细节) metadata Json? createdAt DateTime @default(now()) @map("created_at") poolAccount PoolAccount @relation(fields: [poolAccountId], references: [id]) @@index([poolAccountId, createdAt(sort: Desc)]) @@index([poolType, transactionType]) @@index([counterpartyAccountSeq]) @@index([counterpartyUserId]) @@index([referenceId]) @@index([createdAt(sort: Desc)]) @@map("pool_transactions") } // ==================== Outbox ==================== enum OutboxStatus { PENDING PUBLISHED FAILED } model OutboxEvent { id String @id @default(uuid()) aggregateType String @map("aggregate_type") aggregateId String @map("aggregate_id") eventType String @map("event_type") payload Json topic String @default("mining.events") key String? status OutboxStatus @default(PENDING) retryCount Int @default(0) @map("retry_count") maxRetries Int @default(5) @map("max_retries") lastError String? @map("last_error") publishedAt DateTime? @map("published_at") nextRetryAt DateTime? @map("next_retry_at") createdAt DateTime @default(now()) @map("created_at") @@index([status]) @@index([nextRetryAt]) @@index([createdAt]) @@map("outbox_events") }