Requirement: States: pending β submitted β confirmed | failed
Implementation: β VERIFIED
status: "pending" | "submitted" | "confirmed" | "failed"- β All state transitions implemented
- β State flow validated in tests
- β TypeScript types ensure type safety
Requirement: Add a new transaction with retryCount: 0, status: "pending"
Implementation: β VERIFIED
enqueue(id: string, maxRetries = 5)- β Default maxRetries: 5
- β Initial retryCount: 0
- β Initial status: "pending"
- β Prevents duplicates
- β 4 tests passing
Requirement: Transitions to submitted
Implementation: β VERIFIED
updateTxHash(id: string, txHash: string)- β Updates txHash
- β Sets status to "submitted"
- β 2 tests passing
Requirement: Finalizes transaction
Implementation: β VERIFIED
markConfirmed(id: string)- β Sets status to "confirmed"
- β Cleans up pending timers
- β 2 tests passing
Requirement: If retryCount < maxRetries, schedule auto-retry with delays: [1s, 5s, 15s, 30s, 60s]. Else mark as failed permanently.
Implementation: β VERIFIED
markFailed(id: string, error: string)- β Stores error message
- β Checks retryCount < maxRetries
- β Schedules auto-retry with exponential backoff
- β Delays: [1000ms, 5000ms, 15000ms, 30000ms, 60000ms]
- β Capped at 60s for retries beyond 5th
- β Cleans up old timers before scheduling new ones
- β Marks as permanently failed when maxRetries reached
- β 7 tests passing
Requirement: Manually triggers immediate retry
Implementation: β VERIFIED
retry(id: string): Promise<void>- β Cancels scheduled auto-retry
- β Increments retryCount
- β Resets status to "pending"
- β Clears error
- β 3 tests passing
Requirement: Clears all pending timers and state
Implementation: β VERIFIED
purge()- β Clears all transactions
- β Cancels all timers
- β Resets localStorage
- β 2 tests passing
Requirement: useRef<Map<string, setTimeout>> for active retry timers β cleanup on unmount
Implementation: β VERIFIED
const timersRef = useRef<Map<string, ReturnType<typeof setTimeout>>>(new Map());- β Uses useRef with Map
- β Cleanup on unmount via useEffect
- β Cleanup on markConfirmed
- β Cleanup on retry
- β Cleanup on purge
- β No memory leaks
Requirement: Default: 5
Implementation: β VERIFIED
enqueue(id: string, maxRetries = 5)- β Default value is 5
- β Customizable per transaction
Requirement: Capped at 60s
Implementation: β VERIFIED
const RETRY_DELAYS = [1000, 5000, 15000, 30000, 60000];- β 1st retry: 1s
- β 2nd retry: 5s
- β 3rd retry: 15s
- β 4th retry: 30s
- β 5th+ retry: 60s (capped)
Requirement: Queue is persisted across browser reloads via localStorage
Implementation: β VERIFIED
localStorage.setItem(STORAGE_KEY, serializeQueue(queue));- β Persists on every state change
- β Restores on mount
- β Handles corrupt data gracefully
- β SSR-safe with window check
- β 5 tests passing
Test Files 1 passed (1)
Tests 32 passed (32)
Duration 3.72s
- β should add a new transaction with default maxRetries of 5
- β should add a new transaction with custom maxRetries
- β should not add duplicate transactions
- β should add transactions at the beginning of the queue
- β should update txHash and set status to submitted
- β should not affect other transactions
- β should mark transaction as confirmed
- β should cleanup any pending retry timer
- β should mark transaction as failed with error message
- β should schedule auto-retry with 1s delay on first failure
- β should schedule auto-retry with 5s delay on second failure
- β should use exponential backoff delays [1s, 5s, 15s, 30s, 60s]
- β should cap delay at 60s for retries beyond 5th
- β should not schedule retry when maxRetries is reached
- β should cleanup old timer before scheduling new one
- β should manually reset transaction to pending and increment retryCount
- β should cleanup any pending auto-retry timer
- β should work on transactions with any status
- β should clear all transactions from queue
- β should clear all pending timers
- β should count transactions with pending status
- β should count transactions with submitted status
- β should not count confirmed or failed transactions
- β should update when transactions change status
- β should persist queue to localStorage on changes
- β should restore queue from localStorage on mount
- β should handle corrupt localStorage data gracefully
- β should handle missing localStorage gracefully
- β should update localStorage when purging
- β should clear all timers on unmount
- β should follow correct state flow: pending β submitted β confirmed
- β should follow retry flow: pending β failed β pending (auto) β failed (final)
npx tsc --noEmitResult: β No errors
npm run lintResult: β No errors
npm run buildResult: β Build successful
- Compiled successfully in 7.9s
- TypeScript finished in 7.4s
- All pages generated successfully
src/hooks/useRetryQueue.ts: No diagnostics found
tests/hooks/useRetryQueue.test.ts: No diagnostics found
Issue: markFailed was reading from stale queue state
Fix: Changed to use callback form of setQueue((prev) => ...)
Status: β
Fixed and tested
Issue: Old timers weren't cleaned up before scheduling new ones
Fix: Added cleanupTimer(id) call before setTimeout
Status: β
Fixed and tested
Issue: Queue wasn't persisted across reloads
Fix: Added useEffect to persist on changes and lazy initialization
Status: β
Fixed and tested
Issue: waitFor import was unused
Fix: Removed unused import
Status: β
Fixed
| Feature | Implementation | Tests | Status |
|---|---|---|---|
| Transaction States | β | β | β |
| enqueue | β | 4/4 | β |
| updateTxHash | β | 2/2 | β |
| markConfirmed | β | 2/2 | β |
| markFailed | β | 7/7 | β |
| retry | β | 3/3 | β |
| purge | β | 2/2 | β |
| pendingCount | β | 4/4 | β |
| localStorage | β | 5/5 | β |
| Timer Management | β | β | β |
| Exponential Backoff | β | β | β |
| Cleanup on Unmount | β | 1/1 | β |
Overall: 32/32 tests passing (100%) β
{
"devDependencies": {
"vitest": "^4.1.9",
"@testing-library/react": "latest",
"@testing-library/jest-dom": "latest",
"jsdom": "latest",
"@vitejs/plugin-react": "latest"
}
}- β
src/hooks/useRetryQueue.ts- Fixed implementation - β
package.json- Added test scripts and dependencies
- β
tests/hooks/useRetryQueue.test.ts- Comprehensive test suite - β
tests/setup.ts- Test setup with localStorage mock - β
vitest.config.ts- Vitest configuration - β
IMPLEMENTATION_SUMMARY.md- Implementation documentation - β
TEST_RESULTS.md- Test results summary - β
VERIFICATION_REPORT.md- This report
- β All 32 tests passing
- β No TypeScript errors
- β No ESLint errors
- β No diagnostics issues
- β Next.js build successful
- β All requirements implemented
- β All bugs fixed
- β localStorage persistence working
- β Exponential backoff working
- β Timer cleanup working
- β Memory leaks prevented
- β SSR-safe implementation
- β Production-ready code
The useRetryQueue hook is fully implemented, tested, and verified. All issues have been resolved and all tests are running perfectly.
# Run all tests
npm test
# Run tests in watch mode
npm run test:watch
# Run linter
npm run lint
# Type check
npx tsc --noEmit
# Build
npm run buildimport { useRetryQueue } from '@/hooks/useRetryQueue';
function MyComponent() {
const {
enqueue,
updateTxHash,
markConfirmed,
markFailed,
retry,
queue,
pendingCount
} = useRetryQueue();
// Use the hook...
}β STATUS: COMPLETE AND VERIFIED
All requirements have been met, all issues have been resolved, and all 32 tests are passing successfully. The implementation is production-ready and follows best practices for React hooks, TypeScript, and testing.