/** * Blockchain Client Service * * identity-service 调用 blockchain-service API * - 验证助记词 * - 从助记词派生地址 */ import { Injectable, Logger } from '@nestjs/common'; import { HttpService } from '@nestjs/axios'; import { ConfigService } from '@nestjs/config'; import { firstValueFrom } from 'rxjs'; export interface VerifyMnemonicParams { mnemonic: string; expectedAddresses: Array<{ chainType: string; address: string; }>; } export interface VerifyMnemonicResult { valid: boolean; matchedAddresses: string[]; mismatchedAddresses: string[]; } export interface VerifyMnemonicByAccountParams { accountSequence: string; // 格式: D + YYMMDD + 5位序号 mnemonic: string; } export interface VerifyMnemonicHashResult { valid: boolean; message?: string; } export interface DerivedAddress { chainType: string; address: string; } @Injectable() export class BlockchainClientService { private readonly logger = new Logger(BlockchainClientService.name); private readonly blockchainServiceUrl: string; constructor( private readonly httpService: HttpService, private readonly configService: ConfigService, ) { this.blockchainServiceUrl = this.configService.get( 'BLOCKCHAIN_SERVICE_URL', 'http://blockchain-service:3000', ); this.logger.log(`[INIT] BlockchainClientService initialized`); this.logger.log(`[INIT] URL: ${this.blockchainServiceUrl}`); } /** * 验证助记词是否匹配指定的钱包地址 */ async verifyMnemonic(params: VerifyMnemonicParams): Promise { this.logger.log(`Verifying mnemonic against ${params.expectedAddresses.length} addresses`); try { const response = await firstValueFrom( this.httpService.post( `${this.blockchainServiceUrl}/internal/verify-mnemonic`, { mnemonic: params.mnemonic, expectedAddresses: params.expectedAddresses, }, { headers: { 'Content-Type': 'application/json' }, timeout: 30000, }, ), ); this.logger.log(`Mnemonic verification result: valid=${response.data.valid}`); return response.data; } catch (error) { this.logger.error('Failed to verify mnemonic', error); throw error; } } /** * 通过账户序列号验证助记词(用于账户恢复) */ async verifyMnemonicByAccount(params: VerifyMnemonicByAccountParams): Promise { this.logger.log(`Verifying mnemonic for account ${params.accountSequence}`); try { const response = await firstValueFrom( this.httpService.post( `${this.blockchainServiceUrl}/internal/verify-mnemonic-hash`, { accountSequence: params.accountSequence, mnemonic: params.mnemonic, }, { headers: { 'Content-Type': 'application/json' }, timeout: 30000, }, ), ); this.logger.log(`Mnemonic verification result: valid=${response.data.valid}`); return response.data; } catch (error) { this.logger.error('Failed to verify mnemonic', error); throw error; } } /** * 从助记词派生所有链的钱包地址 */ async deriveFromMnemonic(mnemonic: string): Promise { this.logger.log('Deriving addresses from mnemonic'); try { const response = await firstValueFrom( this.httpService.post<{ addresses: DerivedAddress[] }>( `${this.blockchainServiceUrl}/internal/derive-from-mnemonic`, { mnemonic }, { headers: { 'Content-Type': 'application/json' }, timeout: 30000, }, ), ); this.logger.log(`Derived ${response.data.addresses.length} addresses from mnemonic`); return response.data.addresses; } catch (error) { this.logger.error('Failed to derive addresses from mnemonic', error); throw error; } } /** * 标记助记词已备份 */ async markMnemonicBackedUp(accountSequence: string): Promise { this.logger.log(`Marking mnemonic as backed up for account ${accountSequence}`); try { await firstValueFrom( this.httpService.put( `${this.blockchainServiceUrl}/internal/mnemonic/backup`, { accountSequence }, { headers: { 'Content-Type': 'application/json' }, timeout: 30000, }, ), ); this.logger.log(`Mnemonic marked as backed up for account ${accountSequence}`); } catch (error) { this.logger.error('Failed to mark mnemonic as backed up', error); throw error; } } /** * 挂失助记词 */ async revokeMnemonic(accountSequence: string, reason: string): Promise<{ success: boolean; message: string }> { this.logger.log(`Revoking mnemonic for account ${accountSequence}, reason: ${reason}`); try { const response = await firstValueFrom( this.httpService.post<{ success: boolean; message: string }>( `${this.blockchainServiceUrl}/internal/mnemonic/revoke`, { accountSequence, reason }, { headers: { 'Content-Type': 'application/json' }, timeout: 30000, }, ), ); this.logger.log(`Mnemonic revoke result: success=${response.data.success}`); return response.data; } catch (error) { this.logger.error('Failed to revoke mnemonic', error); throw error; } } }