Task 1-2: Granular Error Codes cho Rental Failures
Phase: 1 Priority: Medium Module:
rentalDepends on: Không có Reference: docs/bountyhunter-blockchain-p2/details/feature-nft-rental/SPEC.md
Background
Hiện tại tất cả lỗi trong RentalService được map vào các error code rất chung: CREATE_RENTAL_FAILED, RETURN_RENTAL_FAILED, RENT_FAILED. Điều này làm cho Backend (và người dùng) không thể phân biệt lý do thất bại cụ thể — số dư không đủ, NFT không thuộc sở hữu, hay contract bị revert do điều kiện nghiệp vụ. Cần thêm subcodes chi tiết bằng cách parse revert reason từ blockchain error.
Tasks
Note: Blockchain revert reason thường nằm trong
error.reason,error.data, hoặcerror.message. Với ethers.js v5:error.reasonhoặcerror.error?.reason. Với Solana: parse từerror.logsarray. Parse cần xảy ra trong catch block trước khi throw hoặc return error response.
- [ ] Định nghĩa granular error codes trong
rental.constants.tshoặcerrors.constants.ts:export const RENTAL_ERROR_CODES = { // Generic (giữ backward compatible) CREATE_RENTAL_FAILED: 'CREATE_RENTAL_FAILED', RETURN_RENTAL_FAILED: 'RETURN_RENTAL_FAILED', RENT_FAILED: 'RENT_FAILED', CANCEL_RENTAL_FAILED: 'CANCEL_RENTAL_FAILED', // Granular subcodes RENTAL_INSUFFICIENT_BALANCE: 'RENTAL_INSUFFICIENT_BALANCE', RENTAL_NFT_NOT_OWNED: 'RENTAL_NFT_NOT_OWNED', RENTAL_CONTRACT_REVERTED: 'RENTAL_CONTRACT_REVERTED', RENTAL_NFT_ALREADY_RENTED: 'RENTAL_NFT_ALREADY_RENTED', RENTAL_PERIOD_EXPIRED: 'RENTAL_PERIOD_EXPIRED', RENTAL_UNSUPPORTED_CHAIN: 'RENTAL_UNSUPPORTED_CHAIN', RENTAL_RPC_TIMEOUT: 'RENTAL_RPC_TIMEOUT', } as const; - [ ] Tạo helper
parseRentalError(error: unknown): string:function parseRentalError(error: unknown): string { const message = error instanceof Error ? error.message : String(error); const reason = (error as any)?.reason ?? ''; if (message.includes('insufficient funds') || reason.includes('insufficient')) { return RENTAL_ERROR_CODES.RENTAL_INSUFFICIENT_BALANCE; } if (reason.includes('not the owner') || message.includes('not owner')) { return RENTAL_ERROR_CODES.RENTAL_NFT_NOT_OWNED; } if (reason.includes('already rented') || reason.includes('isRented')) { return RENTAL_ERROR_CODES.RENTAL_NFT_ALREADY_RENTED; } if (message.includes('timeout') || message.includes('TIMEOUT')) { return RENTAL_ERROR_CODES.RENTAL_RPC_TIMEOUT; } if (message.includes('reverted')) { return RENTAL_ERROR_CODES.RENTAL_CONTRACT_REVERTED; } return RENTAL_ERROR_CODES.CREATE_RENTAL_FAILED; // fallback } - [ ] Cập nhật catch blocks trong
RentalService(vàRentalProcessorsau task-1-1):catch (error) { const errorCode = parseRentalError(error); this.logger.error(`[RENTAL] action=CREATE_RENT errorCode=${errorCode} message=${error.message}`); throw new RpcException({ code: errorCode, message: error.message }); } - [ ] Trả về
errorCodetrong HTTP error response và webhook failure payload
Verification / Acceptance Criteria
- [ ] Simulate
insufficient fundserror từ EVM →errorCode = 'RENTAL_INSUFFICIENT_BALANCE' - [ ] Simulate
not ownerrevert →errorCode = 'RENTAL_NFT_NOT_OWNED' - [ ] Simulate
already rentedrevert →errorCode = 'RENTAL_NFT_ALREADY_RENTED' - [ ] Lỗi không xác định → fallback về generic code (không throw unhandled exception)
- [ ] Error response HTTP có trường
codevới giá trị từRENTAL_ERROR_CODES - [ ] TypeScript compile không có lỗi
Files to Modify
src/rental/rental.service.tssrc/rental/constants/rental.constants.ts(tạo mới hoặc cập nhật)