Skip to content

Conversation

@nijil-deriv
Copy link
Collaborator

🤖 Auto-generated PR

This PR was automatically created by ShiftAI CLI.


chore: remove unclosed AI tag

@nijil-deriv

This comment was marked as outdated.

@claude

This comment was marked as resolved.

@github-actions
Copy link
Contributor

github-actions bot commented Oct 21, 2025

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

OpenSSF Scorecard

PackageVersionScoreDetails

Scanned Manifest Files

@nijil-deriv nijil-deriv changed the title chore: remove unclosed AI tag Nijil / Replace useDtraderQuery with useQuery in AppV2 Oct 21, 2025
@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Oct 21, 2025

Deploying derivatives-trader with  Cloudflare Pages  Cloudflare Pages

Latest commit: 277ded0
Status: ✅  Deploy successful!
Preview URL: https://71e1385b.derivatives-trader.pages.dev
Branch Preview URL: https://refactor-remove-usedtraderqu.derivatives-trader.pages.dev

View logs

@claude

This comment was marked as resolved.

@claude

This comment was marked as resolved.

@claude

This comment was marked as resolved.

matin-deriv
matin-deriv previously approved these changes Oct 23, 2025
@claude

This comment was marked as resolved.

@claude

This comment was marked as resolved.

@claude
Copy link

claude bot commented Nov 5, 2025

Claude finished @nijil-deriv's task —— View job


Code Review Complete ✅

I've completed a comprehensive review of PR #384, which refactors the custom useDtraderQuery hook to use standard useQuery from @deriv/api and introduces a new useProposal hook.


📊 Overall Assessment

Verdict: ✅ APPROVE

This is a well-executed refactoring that successfully standardizes data fetching patterns by migrating from custom hooks to @deriv/api's useQuery. The changes improve maintainability, reduce technical debt, and maintain functional correctness.

Key Metrics:

  • 44 files changed: +868/-1019 lines (net reduction of 151 lines)
  • 3 custom hooks removed: useDtraderQuery.ts, useFetchProposalData.tsx, active-symbols-store.js
  • 1 new hook added: useProposal.tsx
  • Comprehensive test updates with 9 test scenarios covering edge cases
  • No breaking changes to component APIs

🎯 Findings by Priority

Strengths

Architecture & Design

  • ✅ Clean removal of 1000+ lines of custom query logic
  • ✅ Proper use of React Query features (caching, conditional queries, refetchOnWindowFocus: false)
  • ✅ Good separation of concerns with new useProposal hook
  • ✅ Consistent API across all hooks using @deriv/api
  • ✅ Excellent memoization in useProposal (lines 31-47)

Code Quality

  • ✅ Comprehensive test coverage with 9 test scenarios for useProposal
  • ✅ TypeScript types properly used throughout
  • ✅ Clear comments explaining complex logic
  • ✅ Proper error handling using mapErrorMessage
  • ✅ Good use of useCallback and useMemo throughout

Performance

  • ✅ Cache configuration in useActiveSymbols (10-minute cache time)
  • ✅ Proper use of is_enabled flag to conditionally trigger queries
  • cacheTime: 0 in useProposal ensures fresh proposal data (appropriate for real-time pricing)
  • ✅ Memoized proposal request object prevents unnecessary re-renders

Security

  • ✅ No security concerns identified
  • ✅ No XSS vectors
  • ✅ No direct user input passed to API without validation
  • ✅ Error messages properly sanitized with mapErrorMessage

⚠️ Issues Found

1. Type Assertion Bypasses Type Safety (Medium Priority)

Location: packages/trader/src/AppV2/Hooks/useProposal.tsx:50

payload: proposal_request as TPriceProposalRequest,

Issue: Using as TPriceProposalRequest bypasses TypeScript's type checking. If getProposalRequestObject returns an unexpected shape, runtime errors could occur.

Impact: Medium - The code works, but this reduces type safety benefits.

Recommendation: Consider adding runtime validation or use a type guard:

const isValidProposalRequest = (obj: unknown): obj is TPriceProposalRequest => {
    return typeof obj === 'object' && obj !== null && 'proposal' in obj;
};

Decision: Not blocking - The current implementation works and getProposalRequestObject is well-tested. This is defensive programming but not critical for this PR.


2. Multiple Parallel Proposal Requests (Low Priority - Acceptable)

Location: packages/trader/src/AppV2/Components/TradeParameters/Stake/stake-input.tsx:206-225

Two parallel useProposal calls for Rise/Fall contracts:

const { data: response_1, error: error_1, isFetching: is_fetching_1 } = useProposal({...});
const { data: response_2, error: error_2, isFetching: is_fetching_2 } = useProposal({...});

Observation: React Query handles cleanup internally, so no memory leaks expected. The implementation properly checks both is_fetching states before allowing save (lines 394-400).

Status: ✅ Acceptable - Good implementation with proper loading state handling.


3. Large useEffect with Disabled Exhaustive Deps (Low Priority - Pre-existing)

Location: packages/trader/src/AppV2/Hooks/useContractsFor.ts:209

// eslint-disable-next-line react-hooks/exhaustive-deps
}, [response]);

Issue: Large useEffect (lines 122-210) has many undeclared dependencies, which could lead to stale closures.

Impact: Low - This is a pre-existing pattern from the old implementation. No bugs observed.

Recommendation: Consider refactoring in a follow-up PR, but not blocking for this PR.


4. Error Handling Could Be More Granular (Low Priority)

Location: packages/trader/src/AppV2/Hooks/useActiveSymbols.ts:47-51

if (queryError) {
    showError({ message: localize('Failed to load market data. Please refresh the page.') });
}

Observation: Doesn't distinguish between network errors, API errors, or temporary failures.

Impact: Low - Generic error message still provides value to users.

Recommendation: Could add more specific error handling in follow-up:

const errorMessage = queryError?.code === 'NetworkError'
    ? localize('Network connection lost. Please check your connection.')
    : localize('Failed to load market data. Please refresh the page.');

5. No Debouncing on Input Changes (Low Priority)

Location: stake-input.tsx:356-378, take-profit-and-stop-loss-input.tsx:180-191

Observation: Input changes trigger proposal requests immediately on every keystroke.

Impact: Low - React Query's built-in deduplication helps, but could reduce API load further.

Recommendation: Consider adding debouncing (300ms) in follow-up for better UX and reduced API load. Not blocking since current implementation works.


💡 Test Coverage Analysis

Excellent Coverage:

  • ✅ 9 comprehensive test scenarios for useProposal hook
  • ✅ Tests for conditional execution with is_enabled
  • ✅ Tests for skip validation (take profit/stop loss independently)
  • ✅ Tests for incomplete trade store handling
  • ✅ Tests for undefined values in proposal requests
  • ✅ Tests for empty proposal_request_values
  • ✅ Component tests properly mock new hooks

Minor Gaps (not blocking):

  • Error scenarios with specific API error codes could be more comprehensive
  • Concurrent request handling edge cases
  • Rapid re-render edge cases

Status: Test coverage is solid. Missing edge cases are not blockers.


🔍 Detailed Code Analysis

New useProposal Hook (⭐ Excellent)

File: packages/trader/src/AppV2/Hooks/useProposal.tsx

Strengths:

  • Clean API with clear parameter types
  • Proper memoization (lines 31-47) prevents unnecessary re-renders
  • Good handling of skip validation for independent tp/sl validation
  • Appropriate cache settings (cacheTime: 0, retry: false) for real-time pricing
  • Well-documented logic for excluding tp/sl fields

Minor Note: Type assertion on line 50 (noted above in Issue #1).


Modified useActiveSymbols Hook (✅ Good)

File: packages/trader/src/AppV2/Hooks/useActiveSymbols.ts

Strengths:

  • Excellent cache configuration (10-minute cache, lines 13-15)
  • Proper contract type filtering logic (lines 25-29)
  • Good error handling with user-facing messages
  • Clean separation of concerns
  • Proper MobX store updates when data changes

Minor Note: Error handling could be more granular (noted above in Issue #4).


Modified useContractsFor Hook (✅ Acceptable)

File: packages/trader/src/AppV2/Hooks/useContractsFor.ts

Strengths:

  • Complex contract type matching logic preserved correctly (lines 129-153)
  • Enhanced logic to handle Rise/Fall vs Higher/Lower based on contract_category
  • Proper handling of contract categories and config
  • Good use of useCallback for helper functions
  • Fallback logic for API failures (lines 194-203)

Minor Note: Large useEffect with disabled exhaustive-deps (noted above in Issue #3).


Component Changes (✅ Excellent)

Stake Component (stake-input.tsx):

  • ✅ Proper handling of parallel proposals for Rise/Fall (lines 206-225)
  • ✅ Good loading state management with is_loading_proposal
  • ✅ Proper error handling and validation
  • ✅ Edge case handling for Vanilla/Turbo contracts (lines 243-269)
  • ✅ Comprehensive handleProposalResponse function (lines 229-331)

Duration Component (day.tsx):

  • ✅ Good use of useInvalidateQuery for cache management (line 95, 131)
  • ✅ Proper error handling with snackbar messages (lines 98-127)
  • ✅ Edge case handling for payout_per_point and barrier choices
  • ✅ Proper state management for date/time selection

Take Profit/Stop Loss (take-profit-and-stop-loss-input.tsx):

  • ✅ Proper independent validation with should_skip_validation (line 107)
  • ✅ Good use of refs for API response tracking (lines 70-71)
  • ✅ Proper error state management (lines 145-178)
  • ✅ Clean component structure with proper cleanup

🔍 Correctness & Edge Cases

The refactoring maintains functional parity with the previous implementation:

  • ✅ Conditional query execution based on is_enabled
  • ✅ Proper handling of empty/undefined values
  • ✅ Barrier/payout validation logic preserved in components
  • ✅ Independent validation for take profit/stop loss working correctly
  • ✅ Proper cache invalidation in Duration component
  • ✅ Edge case handling for Vanilla contracts (barrier choices in stake-input.tsx:243-253)
  • ✅ Edge case handling for Turbo contracts (payout_per_point choices in stake-input.tsx:256-269)
  • ✅ Proper handling of contract_category to distinguish Rise/Fall from Higher/Lower

🚀 Performance Considerations

  • ✅ React Query's intelligent caching prevents duplicate requests
  • ✅ 10-minute cache in useActiveSymbols reduces API load significantly
  • ✅ Memoization in useProposal hook prevents unnecessary re-renders
  • cacheTime: 0 in useProposal ensures fresh proposal data (appropriate for real-time pricing)
  • ✅ Proper use of enabled flag prevents unnecessary API calls
  • ⚠️ No debouncing on rapid inputs (minor issue, not blocking)

📋 Recommendations

Pre-Merge (Optional)

  1. Consider adding runtime validation for the type assertion in useProposal (15-minute fix, increases type safety)
    • Risk: Very low - current code works fine
    • Benefit: Defensive programming, better error messages if API changes

Post-Merge Follow-Up

  1. Monitor performance in production for any regressions
  2. Consider adding debouncing to input components (Stake, TP/SL) - reduces API load
  3. Track refactoring of large useEffect in useContractsFor - improves maintainability
  4. Add more granular error handling in useActiveSymbols - improves UX
  5. Add missing test cases for edge scenarios (low priority)

📈 Priority Breakdown

Priority Count Blocking? Action
High 0 No None
Medium 1 No Type assertion - consider adding validation
Low 4 No Track in follow-up PRs

🎉 Conclusion

This refactoring successfully achieves its goals and significantly improves the codebase. The migration from custom hooks to standard React Query patterns is well-executed with comprehensive test updates and no breaking changes.

Key Achievements:

  • ✅ Reduced custom code by ~151 lines
  • ✅ Standardized data fetching patterns across the app
  • ✅ Improved performance with proper caching
  • ✅ Maintained functional correctness throughout
  • ✅ Comprehensive test coverage updates (9 test scenarios)
  • ✅ Proactive performance optimization (memoization)
  • ✅ No security concerns
  • ✅ No regressions identified

Why This Should Merge:

  • All identified issues are minor and non-blocking
  • The code is functionally correct and well-tested
  • Performance characteristics are good or improved
  • No security concerns identified
  • The identified issues are about defensive programming and polish, not correctness

Suggested Next Steps:

  1. Merge this PR - It's ready and provides significant value
  2. Monitor for any performance regressions in production
  3. Track follow-up improvements in backlog (debouncing, error handling refinements)

Great work on this refactoring! The codebase is cleaner, more maintainable, and follows better patterns. The migration from custom hooks to standard @deriv/api patterns is well-executed. 🚀


@claude
Copy link

claude bot commented Nov 6, 2025

Claude finished @nijil-deriv's task —— View job


Code Review Complete ✅

I've completed a comprehensive review of PR #384, which refactors custom hooks (useDtraderQuery, useFetchProposalData) to use standard useQuery from @deriv/api and introduces a new useProposal hook.


📊 Overall Assessment

Verdict: ✅ APPROVE with minor observations

This is a solid refactoring that successfully standardizes data fetching patterns while maintaining functional correctness. The migration from custom hooks to standard React Query patterns improves maintainability and reduces technical debt.

Key Metrics:

  • 46 files changed: +878/-1022 lines (net reduction of 144 lines)
  • 3 custom hooks removed: Eliminates technical debt
  • 1 new hook added: useProposal.tsx with clean API
  • Comprehensive test updates: 9 test scenarios covering edge cases
  • No breaking changes to component APIs

🎯 Priority Findings

⚠️ Medium Priority Issues

1. Type Safety Bypassed with Type Assertion

Location: packages/trader/src/AppV2/Hooks/useProposal.tsx:50

payload: proposal_request as TPriceProposalRequest,

Issue: The as TPriceProposalRequest type assertion bypasses TypeScript's type checking. If getProposalRequestObject returns an incompatible shape, runtime errors could occur.

Impact: Reduces type safety benefits. The code works, but defensive programming would add a runtime guard.

Recommendation: Consider adding runtime validation:

const isValidProposalRequest = (obj: unknown): obj is TPriceProposalRequest => {
    return typeof obj === 'object' && obj !== null && 'proposal' in obj;
};

Decision: Not blocking - getProposalRequestObject is well-tested and this pattern is consistent with existing code.


🔍 Low Priority Observations

2. Missing Debouncing on Input Changes

Locations:

  • stake-input.tsx:356-378
  • take-profit-and-stop-loss-input.tsx:180-191

Observation: Input changes trigger proposal API requests immediately on every keystroke. While React Query's deduplication helps, debouncing (e.g., 300ms) would reduce API load further.

Impact: Low - Current implementation works correctly.

Recommendation: Track for future optimization.


3. Large useEffect with Disabled Exhaustive Deps

Locations:

  • useContractsFor.ts:209
  • useActiveSymbols.ts:66
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [response]);

Issue: Large useEffect hooks (122-210 lines in useContractsFor) with many undeclared dependencies could lead to stale closures.

Impact: Low - This pattern existed in the previous implementation. No bugs observed.

Recommendation: Consider refactoring in follow-up PR, but not blocking.


4. Error Handling Could Be More Granular

Location: useActiveSymbols.ts:47-51

if (queryError) {
    showError({ message: localize('Failed to load market data. Please refresh the page.') });
}

Observation: Generic error message doesn't distinguish between network errors, API errors, or temporary failures.

Impact: Low - Still provides value to users.

Recommendation: Consider more specific error handling:

const errorMessage = queryError?.code === 'NetworkError'
    ? localize('Network connection lost. Please check your connection.')
    : localize('Failed to load market data. Please refresh the page.');

✅ Strengths

Architecture & Design

  • ✅ Clean removal of ~144 lines of custom query logic
  • ✅ Proper use of React Query features (cacheTime, conditional queries, refetchOnWindowFocus: false)
  • ✅ Good separation of concerns with new useProposal hook
  • ✅ Consistent API across all hooks using @deriv/api
  • ✅ Excellent memoization in useProposal (lines 31-47)

Code Quality

  • ✅ Comprehensive test coverage with 9 test scenarios for useProposal
    • Tests for conditional execution (is_enabled)
    • Tests for skip validation (tp/sl independently)
    • Tests for incomplete trade store
    • Tests for undefined values
    • Tests for empty proposal_request_values
  • ✅ TypeScript types properly used throughout
  • ✅ Clear comments explaining complex logic
  • ✅ Proper error handling using mapErrorMessage
  • ✅ Good use of useCallback and useMemo

Performance

  • ✅ Cache configuration in useActiveSymbols (10-minute cache time)
  • ✅ Proper use of is_enabled flag to conditionally trigger queries
  • cacheTime: 0 in useProposal ensures fresh proposal data (appropriate for real-time pricing)
  • ✅ Memoized proposal request object prevents unnecessary re-renders

Security

  • ✅ No security concerns identified
  • ✅ No XSS vectors
  • ✅ Error messages properly sanitized with mapErrorMessage

🔍 Detailed Component Analysis

useProposal Hook (⭐ Excellent)

File: packages/trader/src/AppV2/Hooks/useProposal.tsx

Strengths:

  • Clean API with clear parameter types
  • Proper memoization (lines 31-47) prevents unnecessary re-renders
  • Good handling of skip validation for independent tp/sl validation
  • Appropriate cache settings (cacheTime: 0, retry: false) for real-time pricing
  • Well-documented logic for excluding tp/sl fields

Minor Note: Type assertion on line 50 (noted in Issue #1 above).


useActiveSymbols Hook (✅ Good)

File: packages/trader/src/AppV2/Hooks/useActiveSymbols.ts

Strengths:

  • Excellent cache configuration (10-minute cache, lines 13-15)
  • Proper contract type filtering logic (lines 25-29)
  • Good error handling with user-facing messages
  • Clean separation of concerns
  • Proper MobX store updates when data changes

Minor Note: Error handling could be more granular (noted in Issue #4 above).


useContractsFor Hook (✅ Acceptable)

File: packages/trader/src/AppV2/Hooks/useContractsFor.ts

Strengths:

  • Complex contract type matching logic preserved correctly (lines 129-153)
  • Enhanced logic to handle Rise/Fall vs Higher/Lower based on contract_category (lines 134-146)
  • Proper handling of contract categories and config
  • Good use of useCallback for helper functions
  • Fallback logic for API failures (lines 194-203)

Minor Note: Large useEffect with disabled exhaustive-deps (noted in Issue #3 above).


Component Changes

Stake Component (stake-input.tsx) - ✅ Excellent

  • Proper handling of parallel proposals for Rise/Fall (lines 206-225)
  • Good loading state management with is_loading_proposal
  • Proper error handling and validation
  • Edge case handling for Vanilla contracts (lines 243-253):
    if (is_vanilla && queryError?.details?.barrier_choices) {
        const { barrier_choices } = queryError.details;
        if (!barrier_choices?.includes(barrier_1)) {
            const index = Math.floor(barrier_choices.length / 2);
            dispatch({ type: 'SET_PROPOSAL_VALUES', payload: { barrier_1: barrier_choices[index] as number }});
        }
    }
  • Edge case handling for Turbo contracts (lines 256-269)
  • Comprehensive handleProposalResponse function (lines 229-331)

Duration Component (day.tsx) - ✅ Good

  • Good use of useInvalidateQuery for cache management (lines 95, 131)
  • Proper error handling with snackbar messages (lines 98-127)
  • Edge case handling for payout_per_point and barrier choices (lines 102-114)
  • Proper state management for date/time selection

Take Profit/Stop Loss (take-profit-and-stop-loss-input.tsx) - ✅ Good

  • Proper independent validation with should_skip_validation (line 107):
    should_skip_validation: is_take_profit_input ? 'stop_loss' : 'take_profit',
  • Good use of refs for API response tracking (lines 70-71)
  • Proper error state management (lines 145-178)
  • Clean component structure with proper cleanup

🔍 Correctness & Edge Cases

The refactoring maintains functional parity with the previous implementation:

  • ✅ Conditional query execution based on is_enabled
  • ✅ Proper handling of empty/undefined values
  • ✅ Barrier/payout validation logic preserved in components
  • ✅ Independent validation for take profit/stop loss working correctly
  • ✅ Proper cache invalidation in Duration component
  • ✅ Edge case handling for Vanilla contracts (barrier choices)
  • ✅ Edge case handling for Turbo contracts (payout_per_point choices)
  • ✅ Proper handling of contract_category to distinguish Rise/Fall from Higher/Lower (lines 134-146 in useContractsFor.ts)
  • ✅ Parallel proposal requests handled correctly with proper loading states (lines 394-400 in stake-input.tsx)

📋 Test Coverage Analysis

Excellent Coverage:

  • ✅ 9 comprehensive test scenarios for useProposal hook
  • ✅ Tests for conditional execution with is_enabled
  • ✅ Tests for skip validation (take profit/stop loss independently)
  • ✅ Tests for incomplete trade store handling
  • ✅ Tests for undefined values in proposal requests
  • ✅ Tests for empty proposal_request_values
  • ✅ Component tests properly mock new hooks

Minor Gaps (not blocking):

  • Error scenarios with specific API error codes could be more comprehensive
  • Concurrent request handling edge cases
  • Rapid re-render scenarios

Status: Test coverage is solid. Missing edge cases are not blockers.


🚀 Performance Analysis

Optimizations Present:

  • ✅ React Query's intelligent caching prevents duplicate requests
  • ✅ 10-minute cache in useActiveSymbols reduces API load significantly
  • ✅ Memoization in useProposal hook prevents unnecessary re-renders
  • cacheTime: 0 in useProposal ensures fresh proposal data (appropriate for real-time pricing)
  • ✅ Proper use of enabled flag prevents unnecessary API calls

Areas for Future Optimization:

  • ⚠️ No debouncing on rapid inputs (minor issue, not blocking)
  • Consider adding 300ms debounce to stake/tp/sl inputs to reduce API load

📈 Priority Breakdown

Priority Count Blocking? Summary
High 0 No None
Medium 1 No Type assertion - consider adding runtime validation
Low 3 No Track in follow-up PRs

💡 Recommendations

Pre-Merge (Optional, Not Blocking)

  1. Consider adding runtime validation for the type assertion in useProposal.tsx:50
    • Time: ~15 minutes
    • Benefit: Defensive programming, better error messages if API changes
    • Risk: Very low - current code works fine

Post-Merge Follow-Up

  1. Monitor performance in production for any regressions
  2. Consider adding debouncing to input components (Stake, TP/SL) - reduces API load
  3. Track refactoring of large useEffect in useContractsFor - improves maintainability
  4. Add more granular error handling in useActiveSymbols - improves UX
  5. Add missing test cases for edge scenarios (low priority)

🎉 Conclusion

This refactoring successfully achieves its goals and significantly improves the codebase. The migration from custom hooks to standard React Query patterns is well-executed with comprehensive test updates and no breaking changes.

Key Achievements:

  • ✅ Reduced custom code by ~144 lines
  • ✅ Standardized data fetching patterns across the app
  • ✅ Improved performance with proper caching
  • ✅ Maintained functional correctness throughout
  • ✅ Comprehensive test coverage updates (9 test scenarios)
  • ✅ Proactive performance optimization (memoization)
  • ✅ No security concerns
  • ✅ No regressions identified

Why This Should Merge:

  • All identified issues are minor and non-blocking
  • The code is functionally correct and well-tested
  • Performance characteristics are good or improved
  • No security concerns identified
  • The identified issues are about defensive programming and polish, not correctness

Suggested Next Steps:

  1. Merge this PR - It's ready and provides significant value
  2. Monitor for any performance regressions in production
  3. Track follow-up improvements in backlog (debouncing, error handling refinements)

Great work on this refactoring! The codebase is cleaner, more maintainable, and follows better patterns. 🚀


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants