// This is your Prisma schema file, // learn more about it in the docs: https://pris.ly/d/prisma-schema generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } // ============================================ // 监控地址表 // 存储需要监听充值的地址 // ============================================ model MonitoredAddress { id BigInt @id @default(autoincrement()) @map("address_id") chainType String @map("chain_type") @db.VarChar(20) // KAVA, BSC address String @db.VarChar(42) // 0x地址 userId BigInt @map("user_id") // 关联用户ID isActive Boolean @default(true) @map("is_active") // 是否激活监听 createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") deposits DepositTransaction[] @@unique([chainType, address], name: "uk_chain_address") @@index([userId], name: "idx_user") @@index([chainType, isActive], name: "idx_chain_active") @@map("monitored_addresses") } // ============================================ // 充值交易表 (Append-Only) // 记录检测到的所有充值交易 // ============================================ model DepositTransaction { id BigInt @id @default(autoincrement()) @map("deposit_id") chainType String @map("chain_type") @db.VarChar(20) txHash String @unique @map("tx_hash") @db.VarChar(66) fromAddress String @map("from_address") @db.VarChar(42) toAddress String @map("to_address") @db.VarChar(42) tokenContract String @map("token_contract") @db.VarChar(42) // USDT合约地址 amount Decimal @db.Decimal(36, 18) // 原始金额 amountFormatted Decimal @map("amount_formatted") @db.Decimal(20, 8) // 格式化金额 blockNumber BigInt @map("block_number") blockTimestamp DateTime @map("block_timestamp") logIndex Int @map("log_index") // 确认状态 confirmations Int @default(0) status String @default("DETECTED") @db.VarChar(20) // DETECTED, CONFIRMING, CONFIRMED, NOTIFIED // 关联 addressId BigInt @map("address_id") userId BigInt @map("user_id") // 通知状态 notifiedAt DateTime? @map("notified_at") notifyAttempts Int @default(0) @map("notify_attempts") lastNotifyError String? @map("last_notify_error") @db.Text createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") monitoredAddress MonitoredAddress @relation(fields: [addressId], references: [id]) @@index([chainType, status], name: "idx_chain_status") @@index([userId], name: "idx_deposit_user") @@index([blockNumber], name: "idx_block") @@index([status, notifiedAt], name: "idx_pending_notify") @@map("deposit_transactions") } // ============================================ // 区块扫描检查点 (每条链一条记录) // 记录扫描进度,用于断点续扫 // ============================================ model BlockCheckpoint { id BigInt @id @default(autoincrement()) @map("checkpoint_id") chainType String @unique @map("chain_type") @db.VarChar(20) lastScannedBlock BigInt @map("last_scanned_block") lastScannedAt DateTime @map("last_scanned_at") // 健康状态 isHealthy Boolean @default(true) @map("is_healthy") lastError String? @map("last_error") @db.Text createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") @@map("block_checkpoints") } // ============================================ // 交易广播请求表 // 记录待广播和已广播的交易 // ============================================ model TransactionRequest { id BigInt @id @default(autoincrement()) @map("request_id") chainType String @map("chain_type") @db.VarChar(20) // 请求来源 sourceService String @map("source_service") @db.VarChar(50) sourceOrderId String @map("source_order_id") @db.VarChar(100) // 交易数据 fromAddress String @map("from_address") @db.VarChar(42) toAddress String @map("to_address") @db.VarChar(42) value Decimal @db.Decimal(36, 18) data String? @db.Text // 合约调用数据 // 签名数据 (由 MPC 服务提供) signedTx String? @map("signed_tx") @db.Text // 广播结果 txHash String? @map("tx_hash") @db.VarChar(66) status String @default("PENDING") @db.VarChar(20) // PENDING, SIGNED, BROADCASTED, CONFIRMED, FAILED // Gas 信息 gasLimit BigInt? @map("gas_limit") gasPrice Decimal? @map("gas_price") @db.Decimal(36, 18) nonce Int? // 错误信息 errorMessage String? @map("error_message") @db.Text retryCount Int @default(0) @map("retry_count") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") @@unique([sourceService, sourceOrderId], name: "uk_source_order") @@index([chainType, status], name: "idx_tx_chain_status") @@index([txHash], name: "idx_tx_hash") @@map("transaction_requests") } // ============================================ // 区块链事件日志 (Append-Only 审计) // ============================================ model BlockchainEvent { id BigInt @id @default(autoincrement()) @map("event_id") eventType String @map("event_type") @db.VarChar(50) aggregateId String @map("aggregate_id") @db.VarChar(100) aggregateType String @map("aggregate_type") @db.VarChar(50) eventData Json @map("event_data") chainType String? @map("chain_type") @db.VarChar(20) txHash String? @map("tx_hash") @db.VarChar(66) occurredAt DateTime @default(now()) @map("occurred_at") @db.Timestamp(6) @@index([aggregateType, aggregateId], name: "idx_event_aggregate") @@index([eventType], name: "idx_event_type") @@index([chainType], name: "idx_event_chain") @@index([occurredAt], name: "idx_event_occurred") @@map("blockchain_events") }