import { Injectable, Logger, OnModuleInit } from '@nestjs/common'; import { WithdrawalEventConsumerService, WithdrawalRequestedPayload, } from '@/infrastructure/kafka/withdrawal-event-consumer.service'; import { EventPublisherService } from '@/infrastructure/kafka/event-publisher.service'; /** * Withdrawal Requested Event Handler * * Handles withdrawal requests from wallet-service. * For now, logs the event and publishes a status update. * * Future implementation will: * 1. Create TransactionRequest record * 2. Request MPC signing * 3. Broadcast to blockchain * 4. Monitor confirmation */ @Injectable() export class WithdrawalRequestedHandler implements OnModuleInit { private readonly logger = new Logger(WithdrawalRequestedHandler.name); constructor( private readonly withdrawalEventConsumer: WithdrawalEventConsumerService, private readonly eventPublisher: EventPublisherService, ) {} onModuleInit() { this.withdrawalEventConsumer.onWithdrawalRequested( this.handleWithdrawalRequested.bind(this), ); this.logger.log(`[INIT] WithdrawalRequestedHandler registered`); } /** * Handle withdrawal requested event from wallet-service * * Current implementation: Log and acknowledge * TODO: Implement full blockchain transaction flow */ private async handleWithdrawalRequested( payload: WithdrawalRequestedPayload, ): Promise { this.logger.log(`[HANDLE] Received WithdrawalRequested event`); this.logger.log(`[HANDLE] orderNo: ${payload.orderNo}`); this.logger.log(`[HANDLE] accountSequence: ${payload.accountSequence}`); this.logger.log(`[HANDLE] userId: ${payload.userId}`); this.logger.log(`[HANDLE] chainType: ${payload.chainType}`); this.logger.log(`[HANDLE] toAddress: ${payload.toAddress}`); this.logger.log(`[HANDLE] amount: ${payload.amount}`); this.logger.log(`[HANDLE] fee: ${payload.fee}`); this.logger.log(`[HANDLE] netAmount: ${payload.netAmount}`); try { // TODO: Full implementation steps: // 1. Validate the withdrawal request // 2. Get system hot wallet address for the chain // 3. Create TransactionRequest record // 4. Request MPC signing // 5. After signed, broadcast to blockchain // 6. Monitor for confirmation // 7. Publish status updates back to wallet-service // For now, just log that we received it this.logger.log( `[PROCESS] Withdrawal ${payload.orderNo} received for processing`, ); this.logger.log( `[PROCESS] Chain: ${payload.chainType}, To: ${payload.toAddress}, Amount: ${payload.netAmount} USDT`, ); // Publish acknowledgment event (wallet-service can listen for status updates) await this.eventPublisher.publish({ eventType: 'blockchain.withdrawal.received', toPayload: () => ({ orderNo: payload.orderNo, accountSequence: payload.accountSequence, status: 'RECEIVED', message: 'Withdrawal request received by blockchain-service', }), eventId: `wd-received-${payload.orderNo}-${Date.now()}`, occurredAt: new Date(), }); this.logger.log( `[COMPLETE] Withdrawal ${payload.orderNo} acknowledged`, ); // NOTE: Actual blockchain transaction implementation would go here // This would involve: // - Creating a TransactionRequest aggregate // - Calling MPC service for signing // - Broadcasting the signed transaction // - Monitoring for confirmations // - Publishing final status (CONFIRMED or FAILED) } catch (error) { this.logger.error( `[ERROR] Failed to process withdrawal ${payload.orderNo}`, error, ); // Publish failure event await this.eventPublisher.publish({ eventType: 'blockchain.withdrawal.failed', toPayload: () => ({ orderNo: payload.orderNo, accountSequence: payload.accountSequence, status: 'FAILED', error: error instanceof Error ? error.message : 'Unknown error', }), eventId: `wd-failed-${payload.orderNo}-${Date.now()}`, occurredAt: new Date(), }); throw error; } } }