367 lines
9.5 KiB
TypeScript
367 lines
9.5 KiB
TypeScript
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<string, any> {
|
|
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,
|
|
}
|
|
}
|
|
}
|