rwadurian/backend/services/blockchain-service/src/application/event-handlers/withdrawal-requested.handle...

121 lines
4.1 KiB
TypeScript

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<void> {
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;
}
}
}