/** * 账户模型实现 * * 提供账户信息的封装和验证功能 */ import { Account, Platform, Credentials, AccountStatus, CredentialManagerError, ErrorType } from './types'; /** * 账户实体类 */ export class AccountEntity implements Account { public readonly id: string; public readonly platform: Platform; public readonly credentials: Credentials; public status: AccountStatus; public readonly metadata?: Record; constructor(config: { id: string; platform: Platform; credentials: Credentials; metadata?: Record; }) { this.validateAccountConfig(config); this.id = config.id; this.platform = config.platform; this.credentials = config.credentials; this.metadata = config.metadata!; this.status = AccountStatus.LOADING; } /** * 验证账户配置 */ private validateAccountConfig(config: { id: string; platform: Platform; credentials: Credentials; }): void { // 验证账户ID if (!config.id || typeof config.id !== 'string' || config.id.trim().length === 0) { throw new CredentialManagerError( 'Account ID must be a non-empty string', ErrorType.VALIDATION_ERROR, { field: 'id', value: config.id } ); } // 验证平台 if (!Object.values(Platform).includes(config.platform)) { throw new CredentialManagerError( `Invalid platform: ${config.platform}`, ErrorType.VALIDATION_ERROR, { field: 'platform', value: config.platform } ); } // 验证凭证 this.validateCredentials(config.credentials, config.platform); } /** * 验证凭证信息 */ private validateCredentials(credentials: Credentials, platform: Platform): void { if (!credentials || typeof credentials !== 'object') { throw new CredentialManagerError( 'Credentials must be a valid object', ErrorType.VALIDATION_ERROR, { credentials } ); } // 验证凭证类型与平台匹配 const expectedType = platform.toLowerCase(); if (credentials.type !== expectedType) { throw new CredentialManagerError( `Credential type '${credentials.type}' does not match platform '${platform}'`, ErrorType.VALIDATION_ERROR, { credentialType: credentials.type, platform } ); } // 平台特定验证 switch (platform) { case Platform.PACIFICA: this.validatePacificaCredentials(credentials as any); break; case Platform.ASTER: this.validateAsterCredentials(credentials as any); break; case Platform.BINANCE: this.validateBinanceCredentials(credentials as any); break; default: throw new CredentialManagerError( `Unsupported platform: ${platform}`, ErrorType.VALIDATION_ERROR, { platform } ); } } /** * 验证Pacifica凭证 */ private validatePacificaCredentials(credentials: { privateKey: string }): void { if (!credentials.privateKey || typeof credentials.privateKey !== 'string') { throw new CredentialManagerError( 'Pacifica credentials must include a valid privateKey', ErrorType.VALIDATION_ERROR, { field: 'privateKey' } ); } // 验证Ed25519私钥格式(64字符十六进制) const privateKeyRegex = /^[0-9a-fA-F]{64}$/; if (!privateKeyRegex.test(credentials.privateKey)) { throw new CredentialManagerError( 'Pacifica privateKey must be a 64-character hexadecimal string', ErrorType.VALIDATION_ERROR, { privateKey: credentials.privateKey.substring(0, 10) + '...' } ); } } /** * 验证Aster凭证 */ private validateAsterCredentials(credentials: { privateKey: string }): void { if (!credentials.privateKey || typeof credentials.privateKey !== 'string') { throw new CredentialManagerError( 'Aster credentials must include a valid privateKey', ErrorType.VALIDATION_ERROR, { field: 'privateKey' } ); } // 验证以太坊私钥格式(0x前缀 + 64字符十六进制) const ethPrivateKeyRegex = /^0x[0-9a-fA-F]{64}$/i; if (!ethPrivateKeyRegex.test(credentials.privateKey)) { throw new CredentialManagerError( 'Aster privateKey must be a valid Ethereum private key (0x + 64 hex characters)', ErrorType.VALIDATION_ERROR, { privateKey: credentials.privateKey.substring(0, 10) + '...' } ); } } /** * 验证Binance凭证 */ private validateBinanceCredentials(credentials: { apiKey: string; secretKey: string }): void { if (!credentials.apiKey || typeof credentials.apiKey !== 'string') { throw new CredentialManagerError( 'Binance credentials must include a valid apiKey', ErrorType.VALIDATION_ERROR, { field: 'apiKey' } ); } if (!credentials.secretKey || typeof credentials.secretKey !== 'string') { throw new CredentialManagerError( 'Binance credentials must include a valid secretKey', ErrorType.VALIDATION_ERROR, { field: 'secretKey' } ); } // 基本长度验证 if (credentials.apiKey.trim().length === 0) { throw new CredentialManagerError( 'Binance apiKey cannot be empty', ErrorType.VALIDATION_ERROR, { field: 'apiKey' } ); } if (credentials.secretKey.trim().length === 0) { throw new CredentialManagerError( 'Binance secretKey cannot be empty', ErrorType.VALIDATION_ERROR, { field: 'secretKey' } ); } } /** * 设置账户状态 */ public setStatus(status: AccountStatus): void { this.status = status; } /** * 检查账户是否处于活跃状态 */ public isActive(): boolean { return this.status === AccountStatus.ACTIVE; } /** * 获取账户的安全信息(隐藏敏感数据) */ public toSafeObject(): Omit & { credentialsType: string } { return { id: this.id, platform: this.platform, status: this.status, metadata: this.metadata, credentialsType: this.credentials.type, }; } /** * 克隆账户(深拷贝) */ public clone(): AccountEntity { return new AccountEntity({ id: this.id, platform: this.platform, credentials: JSON.parse(JSON.stringify(this.credentials)), metadata: this.metadata ? JSON.parse(JSON.stringify(this.metadata)) : undefined, }); } /** * 比较两个账户是否相等 */ public equals(other: Account): boolean { return ( this.id === other.id && this.platform === other.platform && JSON.stringify(this.credentials) === JSON.stringify(other.credentials) ); } /** * 获取账户的字符串表示 */ public toString(): string { return `Account(id=${this.id}, platform=${this.platform}, status=${this.status})`; } } /** * 账户工厂函数 */ export function createAccount(config: { id: string; platform: Platform; credentials: Credentials; metadata?: Record; }): AccountEntity { return new AccountEntity(config); } /** * 从配置创建账户 */ export function createAccountFromConfig(config: any): AccountEntity { if (!config || typeof config !== 'object') { throw new CredentialManagerError( 'Account config must be a valid object', ErrorType.VALIDATION_ERROR, { config } ); } // 转换平台字符串为枚举 let platform: Platform; if (typeof config.platform === 'string') { const platformValue = config.platform.toLowerCase(); switch (platformValue) { case 'pacifica': platform = Platform.PACIFICA; break; case 'aster': platform = Platform.ASTER; break; case 'binance': platform = Platform.BINANCE; break; default: throw new CredentialManagerError( `Unsupported platform: ${config.platform}`, ErrorType.VALIDATION_ERROR, { platform: config.platform } ); } } else { throw new CredentialManagerError( 'Platform must be a valid string', ErrorType.VALIDATION_ERROR, { platform: config.platform } ); } return new AccountEntity({ id: config.id, platform, credentials: config.credentials, metadata: config.metadata, }); }