324 lines
12 KiB
Plaintext
324 lines
12 KiB
Plaintext
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")
|
||
}
|