Task 2-2: Structured Error Payload cho Webhooks
Phase: 2 Priority: Low Module:
marketplaceDepends on: Không có Reference: docs/bountyhunter-blockchain-p2/details/feature-marketplace/SPEC.md
Background
Hiện tại webhook failure payload gửi về Backend có trường error là kết quả của error.toString() — raw JavaScript error message, không có cấu trúc. Backend phải parse string để hiểu lỗi, dễ dẫn đến sai sót và khó xử lý tự động. Cần thêm errorCode theo định nghĩa trước để Backend có thể phân loại và xử lý lỗi một cách programmatic.
Tasks
Note: Error code constants nên được định nghĩa trong
marketplace.constants.ts(hoặc file constants chung). Khi thêmerrorCodevào payload, cần đảm bảo backward compatible —errormessage vẫn giữ nguyên, chỉ thêm fielderrorCode. Phân tích blockchain error phải được làm trước khi map vào error code.
- [ ] Định nghĩa error code constants trong
marketplace.constants.ts:export const MARKETPLACE_ERROR_CODES = { // On-chain errors TX_REVERTED: 'MARKETPLACE_TX_REVERTED', INSUFFICIENT_GAS: 'MARKETPLACE_INSUFFICIENT_GAS', NFT_NOT_OWNED: 'MARKETPLACE_NFT_NOT_OWNED', NFT_ALREADY_LISTED: 'MARKETPLACE_NFT_ALREADY_LISTED', INVALID_PRICE: 'MARKETPLACE_INVALID_PRICE', // Network errors RPC_TIMEOUT: 'MARKETPLACE_RPC_TIMEOUT', NETWORK_UNAVAILABLE: 'MARKETPLACE_NETWORK_UNAVAILABLE', // Generic UNKNOWN_ERROR: 'MARKETPLACE_UNKNOWN_ERROR', } as const; export type MarketplaceErrorCode = typeof MARKETPLACE_ERROR_CODES[keyof typeof MARKETPLACE_ERROR_CODES]; - [ ] Tạo helper
parseBlockchainError(error: unknown): MarketplaceErrorCode:function parseBlockchainError(error: unknown): MarketplaceErrorCode { const message = error instanceof Error ? error.message : String(error); if (message.includes('reverted')) return MARKETPLACE_ERROR_CODES.TX_REVERTED; if (message.includes('insufficient funds')) return MARKETPLACE_ERROR_CODES.INSUFFICIENT_GAS; if (message.includes('not the owner')) return MARKETPLACE_ERROR_CODES.NFT_NOT_OWNED; if (message.includes('timeout')) return MARKETPLACE_ERROR_CODES.RPC_TIMEOUT; return MARKETPLACE_ERROR_CODES.UNKNOWN_ERROR; } - [ ] Cập nhật failure webhook payload trong
notifyWebhookOrRetry(task-1-2) và trong từng handler:// Trước: await postWithRetry(webhookUrl, { status: 'FAILED', error: error.toString() }); // Sau: await postWithRetry(webhookUrl, { status: 'FAILED', error: error instanceof Error ? error.message : String(error), errorCode: parseBlockchainError(error), }); - [ ] Áp dụng cho tất cả failure webhook calls trong processor và service
Verification / Acceptance Criteria
- [ ] Failure webhook payload có trường
errorCodevới giá trị là một trongMARKETPLACE_ERROR_CODES - [ ]
errorfield vẫn là string (backward compatible với Backend hiện tại) - [ ] Simulate
reverterror từ EVM →errorCode = 'MARKETPLACE_TX_REVERTED' - [ ] Simulate timeout error →
errorCode = 'MARKETPLACE_RPC_TIMEOUT' - [ ] Lỗi không xác định →
errorCode = 'MARKETPLACE_UNKNOWN_ERROR' - [ ] TypeScript:
errorCodecó kiểuMarketplaceErrorCode(không phảistring) - [ ] Compile không có lỗi
Files to Modify
src/marketplace/marketplace.constants.tssrc/marketplace/marketplace.processor.ts