rwadurian/backend/services/mining-service/prisma/schema.prisma

453 lines
18 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 // 当前纪元开始日期
secondDistribution 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) // 已分配量
secondDistribution 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) // 当时的总算力
secondDistribution 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 MiningRewardAllocation {
id BigInt @id @default(autoincrement())
// ========== 挖矿日期 ==========
miningDate DateTime @map("mining_date") @db.Date
// ========== 算力来源(可追溯到认种)==========
contributionRecordId BigInt @map("contribution_record_id") // 关联 contribution-service 的算力明细记录ID
sourceAdoptionId BigInt @map("source_adoption_id") // 来源认种ID
sourceAccountSequence String @map("source_account_sequence") @db.VarChar(20) // 认种人账号
// ========== 算力归属账户 ==========
ownerAccountSequence String @map("owner_account_sequence") @db.VarChar(20) // 算力归属账户(收到分成的上级)
// ========== 算力类型 ==========
contributionType String @map("contribution_type") @db.VarChar(30) // PERSONAL / LEVEL_1~15 / BONUS_TIER_1~3
// ========== 算力金额与挖矿收益 ==========
contributionAmount Decimal @map("contribution_amount") @db.Decimal(30, 10) // 参与挖矿的算力
networkTotalContribution Decimal @map("network_total_contribution") @db.Decimal(30, 10) // 当日全网算力
contributionRatio Decimal @map("contribution_ratio") @db.Decimal(30, 18) // 算力占比
dailyMiningPool Decimal @map("daily_mining_pool") @db.Decimal(30, 10) // 当日挖矿池总量
rewardAmount Decimal @map("reward_amount") @db.Decimal(30, 10) // 应得挖矿收益
// ========== 分配状态(核心:是否因未解锁而归总部)==========
allocationStatus String @map("allocation_status") @db.VarChar(20) // TO_USER / TO_HEADQUARTERS
isUnlocked Boolean @map("is_unlocked") // 算力是否已解锁
// ========== 实际分配去向 ==========
allocatedToAccountSequence String? @map("allocated_to_account_sequence") @db.VarChar(20) // 实际分配给的账户
allocatedToSystemAccount String? @map("allocated_to_system_account") @db.VarChar(20) // 或分配给系统账户HEADQUARTERS
// ========== 未解锁原因说明 ==========
unlockedReason String? @map("unlocked_reason") @db.VarChar(200) // 如果归总部,记录原因
// ========== 资质条件快照(便于追溯)==========
ownerHasAdopted Boolean @map("owner_has_adopted") // 归属账户当时是否已认种
ownerDirectReferralCount Int @map("owner_direct_referral_count") // 归属账户当时直推认种人数
ownerUnlockedLevelDepth Int @map("owner_unlocked_level_depth") // 归属账户当时解锁层级深度
ownerUnlockedBonusTiers Int @map("owner_unlocked_bonus_tiers") // 归属账户当时解锁加成档位
// ========== 备注 ==========
remark String? @map("remark") @db.VarChar(500)
createdAt DateTime @default(now()) @map("created_at")
@@index([miningDate])
@@index([ownerAccountSequence, miningDate])
@@index([sourceAccountSequence])
@@index([sourceAdoptionId])
@@index([allocationStatus])
@@index([contributionRecordId])
@@map("mining_reward_allocations")
}
// 每日挖矿汇总(按账户)
// 汇总每个账户每天的挖矿收益
model DailyMiningRewardSummary {
id BigInt @id @default(autoincrement())
miningDate DateTime @map("mining_date") @db.Date
accountSequence String @map("account_sequence") @db.VarChar(20)
// ========== 收益汇总 ==========
// 来自已解锁算力的收益(归用户)
unlockedReward Decimal @default(0) @map("unlocked_reward") @db.Decimal(30, 10)
// 来自待解锁算力的收益(本应归用户,但因未解锁归了总部)
pendingRewardToHq Decimal @default(0) @map("pending_reward_to_hq") @db.Decimal(30, 10)
// ========== 明细统计 ==========
// 已解锁的各类算力收益
personalReward Decimal @default(0) @map("personal_reward") @db.Decimal(30, 10) // 个人算力收益
levelReward Decimal @default(0) @map("level_reward") @db.Decimal(30, 10) // 层级算力收益(已解锁部分)
bonusReward Decimal @default(0) @map("bonus_reward") @db.Decimal(30, 10) // 加成算力收益(已解锁部分)
// 待解锁转总部的明细
pendingLevelToHq Decimal @default(0) @map("pending_level_to_hq") @db.Decimal(30, 10) // 待解锁层级收益归总部
pendingBonusToHq Decimal @default(0) @map("pending_bonus_to_hq") @db.Decimal(30, 10) // 待解锁加成收益归总部
createdAt DateTime @default(now()) @map("created_at")
@@unique([miningDate, accountSequence])
@@index([miningDate])
@@index([accountSequence])
@@map("daily_mining_reward_summaries")
}
// 总部待解锁收益明细账
// 记录总部收到的来自各用户待解锁算力的收益
model HeadquartersPendingReward {
id BigInt @id @default(autoincrement())
miningDate DateTime @map("mining_date") @db.Date
// ========== 应归属账户(如果解锁了会归他)==========
wouldBeAccountSequence String @map("would_be_account_sequence") @db.VarChar(20)
// ========== 算力来源 ==========
sourceAdoptionId BigInt @map("source_adoption_id")
sourceAccountSequence String @map("source_account_sequence") @db.VarChar(20)
contributionRecordId BigInt @map("contribution_record_id")
// ========== 算力类型与金额 ==========
contributionType String @map("contribution_type") @db.VarChar(30) // LEVEL_1~15 / BONUS_TIER_1~3
contributionAmount Decimal @map("contribution_amount") @db.Decimal(30, 10)
rewardAmount Decimal @map("reward_amount") @db.Decimal(30, 10)
// ========== 未解锁原因 ==========
reason String @map("reason") @db.VarChar(200) // 如 "账户未认种层级1-5未解锁" / "直推认种人数不足3人层级6-10未解锁"
// ========== 资质条件快照 ==========
ownerHasAdopted Boolean @map("owner_has_adopted")
ownerDirectReferralCount Int @map("owner_direct_referral_count")
requiredCondition String @map("required_condition") @db.VarChar(100) // 需要满足的条件
createdAt DateTime @default(now()) @map("created_at")
@@index([miningDate])
@@index([wouldBeAccountSequence])
@@index([sourceAdoptionId])
@@map("headquarters_pending_rewards")
}
// ==================== 挖矿统计 ====================
// 每分钟挖矿统计
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")
}