import { AggregateRoot } from './aggregate-root.base' import { SystemAccountType, SystemLedgerEntryType, SystemAccountStatus } from '@/domain/enums' import { DomainError } from '@/shared/exceptions' import { SystemAccountCreatedEvent, SystemAccountWalletGeneratedEvent, SystemAccountFundsReceivedEvent, SystemAccountFundsTransferredEvent, } from '@/domain/events' import Decimal from 'decimal.js' export interface SystemAccountProps { id: bigint accountType: SystemAccountType regionCode: string | null regionName: string | null walletAddress: string | null mpcPublicKey: string | null usdtBalance: Decimal hashpower: Decimal totalReceived: Decimal totalTransferred: Decimal status: SystemAccountStatus createdAt: Date updatedAt: Date } export interface SystemAccountLedgerEntryProps { id: bigint accountId: bigint entryType: SystemLedgerEntryType amount: Decimal balanceAfter: Decimal sourceOrderId: bigint | null sourceRewardId: bigint | null txHash: string | null memo: string | null createdAt: Date } export class SystemAccount extends AggregateRoot { private _id: bigint private _accountType: SystemAccountType private _regionCode: string | null private _regionName: string | null private _walletAddress: string | null private _mpcPublicKey: string | null private _usdtBalance: Decimal private _hashpower: Decimal private _totalReceived: Decimal private _totalTransferred: Decimal private _status: SystemAccountStatus private _createdAt: Date private _updatedAt: Date // Getters get id(): bigint { return this._id } get accountType(): SystemAccountType { return this._accountType } get regionCode(): string | null { return this._regionCode } get regionName(): string | null { return this._regionName } get walletAddress(): string | null { return this._walletAddress } get mpcPublicKey(): string | null { return this._mpcPublicKey } get usdtBalance(): Decimal { return this._usdtBalance } get hashpower(): Decimal { return this._hashpower } get totalReceived(): Decimal { return this._totalReceived } get totalTransferred(): Decimal { return this._totalTransferred } get status(): SystemAccountStatus { return this._status } get createdAt(): Date { return this._createdAt } get updatedAt(): Date { return this._updatedAt } get isActive(): boolean { return this._status === SystemAccountStatus.ACTIVE } get hasWallet(): boolean { return this._walletAddress !== null } // 私有构造函数 private constructor(props: SystemAccountProps) { super() this._id = props.id this._accountType = props.accountType this._regionCode = props.regionCode this._regionName = props.regionName this._walletAddress = props.walletAddress this._mpcPublicKey = props.mpcPublicKey this._usdtBalance = props.usdtBalance this._hashpower = props.hashpower this._totalReceived = props.totalReceived this._totalTransferred = props.totalTransferred this._status = props.status this._createdAt = props.createdAt this._updatedAt = props.updatedAt } // 工厂方法 - 从数据库重建 static fromPersistence(props: SystemAccountProps): SystemAccount { return new SystemAccount(props) } // 工厂方法 - 创建固定系统账户(成本、运营、总部社区、矿池) static createFixedAccount(accountType: SystemAccountType): SystemAccount { if ( accountType === SystemAccountType.SYSTEM_PROVINCE || accountType === SystemAccountType.SYSTEM_CITY ) { throw new DomainError('区域系统账户需要指定区域信息') } const account = new SystemAccount({ id: BigInt(0), // 由数据库生成 accountType, regionCode: null, regionName: null, walletAddress: null, mpcPublicKey: null, usdtBalance: new Decimal(0), hashpower: new Decimal(0), totalReceived: new Decimal(0), totalTransferred: new Decimal(0), status: SystemAccountStatus.ACTIVE, createdAt: new Date(), updatedAt: new Date(), }) account.addDomainEvent( new SystemAccountCreatedEvent({ accountType, regionCode: null, }), ) return account } // 工厂方法 - 创建区域系统账户(省/市) static createRegionAccount(params: { accountType: SystemAccountType.SYSTEM_PROVINCE | SystemAccountType.SYSTEM_CITY regionCode: string regionName: string }): SystemAccount { const account = new SystemAccount({ id: BigInt(0), // 由数据库生成 accountType: params.accountType, regionCode: params.regionCode, regionName: params.regionName, walletAddress: null, mpcPublicKey: null, usdtBalance: new Decimal(0), hashpower: new Decimal(0), totalReceived: new Decimal(0), totalTransferred: new Decimal(0), status: SystemAccountStatus.ACTIVE, createdAt: new Date(), updatedAt: new Date(), }) account.addDomainEvent( new SystemAccountCreatedEvent({ accountType: params.accountType, regionCode: params.regionCode, }), ) return account } // 核心领域行为 /** * 设置 MPC 生成的钱包地址 */ setWalletAddress(walletAddress: string, mpcPublicKey: string): void { if (this._walletAddress) { throw new DomainError('钱包地址已设置,不能重复设置') } this._walletAddress = walletAddress this._mpcPublicKey = mpcPublicKey this._updatedAt = new Date() this.addDomainEvent( new SystemAccountWalletGeneratedEvent({ accountId: this._id.toString(), accountType: this._accountType, walletAddress, mpcPublicKey, }), ) } /** * 接收资金(从认种分配或过期奖励) */ receiveFunds(params: { amount: Decimal entryType: SystemLedgerEntryType sourceOrderId?: bigint sourceRewardId?: bigint txHash?: string memo?: string }): SystemAccountLedgerEntryProps { if (!this.isActive) { throw new DomainError('系统账户已停用') } if (params.amount.lte(0)) { throw new DomainError('金额必须大于0') } const newBalance = this._usdtBalance.plus(params.amount) this._usdtBalance = newBalance this._totalReceived = this._totalReceived.plus(params.amount) this._updatedAt = new Date() const ledgerEntry: SystemAccountLedgerEntryProps = { id: BigInt(0), // 由数据库生成 accountId: this._id, entryType: params.entryType, amount: params.amount, balanceAfter: newBalance, sourceOrderId: params.sourceOrderId || null, sourceRewardId: params.sourceRewardId || null, txHash: params.txHash || null, memo: params.memo || null, createdAt: new Date(), } this.addDomainEvent( new SystemAccountFundsReceivedEvent({ accountId: this._id.toString(), accountType: this._accountType, amount: params.amount.toString(), entryType: params.entryType, balanceAfter: newBalance.toString(), }), ) return ledgerEntry } /** * 转出资金 */ transferFunds(params: { amount: Decimal txHash?: string memo?: string }): SystemAccountLedgerEntryProps { if (!this.isActive) { throw new DomainError('系统账户已停用') } if (params.amount.lte(0)) { throw new DomainError('金额必须大于0') } if (this._usdtBalance.lt(params.amount)) { throw new DomainError('余额不足') } const newBalance = this._usdtBalance.minus(params.amount) this._usdtBalance = newBalance this._totalTransferred = this._totalTransferred.plus(params.amount) this._updatedAt = new Date() const ledgerEntry: SystemAccountLedgerEntryProps = { id: BigInt(0), accountId: this._id, entryType: SystemLedgerEntryType.TRANSFER_OUT, amount: params.amount.neg(), balanceAfter: newBalance, sourceOrderId: null, sourceRewardId: null, txHash: params.txHash || null, memo: params.memo || null, createdAt: new Date(), } this.addDomainEvent( new SystemAccountFundsTransferredEvent({ accountId: this._id.toString(), accountType: this._accountType, amount: params.amount.toString(), txHash: params.txHash || null, balanceAfter: newBalance.toString(), }), ) return ledgerEntry } /** * 增加算力 */ addHashpower(amount: Decimal): void { if (amount.lte(0)) { throw new DomainError('算力必须大于0') } this._hashpower = this._hashpower.plus(amount) this._updatedAt = new Date() } /** * 停用账户 */ deactivate(): void { this._status = SystemAccountStatus.INACTIVE this._updatedAt = new Date() } /** * 激活账户 */ activate(): void { this._status = SystemAccountStatus.ACTIVE this._updatedAt = new Date() } /** * 转换为持久化数据 */ toPersistence(): Record { return { id: this._id, accountType: this._accountType, regionCode: this._regionCode, regionName: this._regionName, walletAddress: this._walletAddress, mpcPublicKey: this._mpcPublicKey, usdtBalance: this._usdtBalance, hashpower: this._hashpower, totalReceived: this._totalReceived, totalTransferred: this._totalTransferred, status: this._status, createdAt: this._createdAt, updatedAt: this._updatedAt, } } }