feat(mpc-service): add blockchain-service client for address derivation
- Add BlockchainClientService to call blockchain-service /internal/derive-address - Call derive addresses after keygen completes with MPC public key - Include derived addresses (BSC, KAVA, DST) in keygen completed event 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
cf308efecf
commit
0ab1bf0dcc
|
|
@ -14,6 +14,7 @@ import {
|
|||
KeygenRequestedPayload,
|
||||
} from '../../infrastructure/messaging/kafka/event-consumer.service';
|
||||
import { BackupClientService } from '../../infrastructure/external/backup';
|
||||
import { BlockchainClientService } from '../../infrastructure/external/blockchain';
|
||||
import { KeygenStartedEvent } from '../../domain/events/keygen-started.event';
|
||||
import { KeygenCompletedEvent } from '../../domain/events/keygen-completed.event';
|
||||
import { SessionFailedEvent } from '../../domain/events/session-failed.event';
|
||||
|
|
@ -28,6 +29,7 @@ export class KeygenRequestedHandler implements OnModuleInit {
|
|||
private readonly eventPublisher: EventPublisherService,
|
||||
private readonly mpcCoordinator: MPCCoordinatorService,
|
||||
private readonly backupClient: BackupClientService,
|
||||
private readonly blockchainClient: BlockchainClientService,
|
||||
) {}
|
||||
|
||||
async onModuleInit() {
|
||||
|
|
@ -74,6 +76,20 @@ export class KeygenRequestedHandler implements OnModuleInit {
|
|||
// Cache public key
|
||||
await this.mpcCoordinator.savePublicKeyCache(username, result.publicKey);
|
||||
|
||||
// Step 3: Derive addresses for all chains (BSC, KAVA, DST) via blockchain-service
|
||||
let derivedAddresses: { chainType: string; address: string }[] = [];
|
||||
try {
|
||||
const deriveResult = await this.blockchainClient.deriveAddresses({
|
||||
userId,
|
||||
publicKey: result.publicKey,
|
||||
});
|
||||
derivedAddresses = deriveResult.addresses;
|
||||
this.logger.log(`Addresses derived: userId=${userId}, count=${derivedAddresses.length}`);
|
||||
} catch (deriveError) {
|
||||
// 地址派生失败不阻塞主流程,但记录错误
|
||||
this.logger.error(`Failed to derive addresses: userId=${userId}`, deriveError);
|
||||
}
|
||||
|
||||
// Save delegate share to backup-service if exists
|
||||
if (result.delegateShare) {
|
||||
// 1. 保存到本地缓存(用于签名时快速访问)
|
||||
|
|
@ -115,6 +131,7 @@ export class KeygenRequestedHandler implements OnModuleInit {
|
|||
userId,
|
||||
username,
|
||||
delegateShare: result.delegateShare,
|
||||
derivedAddresses, // BSC, KAVA, DST addresses
|
||||
serverParties: [], // mpc-system manages this
|
||||
};
|
||||
|
||||
|
|
|
|||
102
backend/services/mpc-service/src/infrastructure/external/blockchain/blockchain-client.service.ts
vendored
Normal file
102
backend/services/mpc-service/src/infrastructure/external/blockchain/blockchain-client.service.ts
vendored
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
/**
|
||||
* Blockchain Client Service
|
||||
*
|
||||
* mpc-service 调用 blockchain-service 派生钱包地址
|
||||
*/
|
||||
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
import { HttpService } from '@nestjs/axios';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
|
||||
export interface DeriveAddressParams {
|
||||
userId: string;
|
||||
publicKey: string;
|
||||
}
|
||||
|
||||
export interface DerivedAddress {
|
||||
chainType: string;
|
||||
address: string;
|
||||
}
|
||||
|
||||
export interface DeriveAddressResult {
|
||||
userId: string;
|
||||
publicKey: string;
|
||||
addresses: DerivedAddress[];
|
||||
}
|
||||
|
||||
@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<string>(
|
||||
'BLOCKCHAIN_SERVICE_URL',
|
||||
'http://blockchain-service:3000',
|
||||
);
|
||||
this.logger.log(`[INIT] BlockchainClientService initialized`);
|
||||
this.logger.log(`[INIT] URL: ${this.blockchainServiceUrl}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从公钥派生多链地址 (BSC, KAVA, DST)
|
||||
*/
|
||||
async deriveAddresses(params: DeriveAddressParams): Promise<DeriveAddressResult> {
|
||||
this.logger.log(`Deriving addresses: userId=${params.userId}, publicKey=${params.publicKey.substring(0, 20)}...`);
|
||||
|
||||
try {
|
||||
const response = await firstValueFrom(
|
||||
this.httpService.post<DeriveAddressResult>(
|
||||
`${this.blockchainServiceUrl}/internal/derive-address`,
|
||||
{
|
||||
userId: params.userId,
|
||||
publicKey: params.publicKey,
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
timeout: 30000,
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
this.logger.log(`Addresses derived successfully: userId=${params.userId}, count=${response.data.addresses.length}`);
|
||||
for (const addr of response.data.addresses) {
|
||||
this.logger.log(` ${addr.chainType}: ${addr.address}`);
|
||||
}
|
||||
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
this.logger.error(`Failed to derive addresses: userId=${params.userId}`, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户已有的地址
|
||||
*/
|
||||
async getUserAddresses(userId: string): Promise<DerivedAddress[]> {
|
||||
this.logger.log(`Getting user addresses: userId=${userId}`);
|
||||
|
||||
try {
|
||||
const response = await firstValueFrom(
|
||||
this.httpService.get<{ userId: string; addresses: DerivedAddress[] }>(
|
||||
`${this.blockchainServiceUrl}/internal/user/${userId}/addresses`,
|
||||
{
|
||||
timeout: 30000,
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
return response.data.addresses;
|
||||
} catch (error) {
|
||||
this.logger.error(`Failed to get user addresses: userId=${userId}`, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
export * from './blockchain-client.service';
|
||||
|
|
@ -5,6 +5,7 @@
|
|||
* - PrismaService 用于缓存公钥和 delegate share
|
||||
* - Kafka 事件发布和消费
|
||||
* - BackupClientService 用于存储 delegate share 到 backup-service
|
||||
* - BlockchainClientService 用于派生钱包地址
|
||||
*/
|
||||
|
||||
import { Global, Module } from '@nestjs/common';
|
||||
|
|
@ -20,6 +21,7 @@ import { EventConsumerService } from './messaging/kafka/event-consumer.service';
|
|||
|
||||
// External Services
|
||||
import { BackupClientService } from './external/backup';
|
||||
import { BlockchainClientService } from './external/blockchain';
|
||||
|
||||
@Global()
|
||||
@Module({
|
||||
|
|
@ -40,12 +42,14 @@ import { BackupClientService } from './external/backup';
|
|||
|
||||
// External Services
|
||||
BackupClientService,
|
||||
BlockchainClientService,
|
||||
],
|
||||
exports: [
|
||||
PrismaService,
|
||||
EventPublisherService,
|
||||
EventConsumerService,
|
||||
BackupClientService,
|
||||
BlockchainClientService,
|
||||
],
|
||||
})
|
||||
export class InfrastructureModule {}
|
||||
|
|
|
|||
Loading…
Reference in New Issue