Skip to content

Commit b23a0c7

Browse files
authored
feat: Integrate season status hook in PerpsHeroCardView (MetaMask#22768)
## **Description** This PR completes the fix for missing MetaMask referral code display in the Perps PnL Hero Card. PR MetaMask#22175 attempted to fix this issue but was incomplete due to a missing data dependency. ### What is the reason for the change? Despite PR MetaMask#22175 adding the `useReferralDetails()` hook to fetch referral codes, users reported that the referral code still only appears **after** visiting the Rewards page first. Investigation revealed a critical dependency chain issue: - `useReferralDetails()` requires both `subscriptionId` and `seasonId` to fetch data - If either is missing, the hook returns early without fetching - `seasonId` is only populated by `useSeasonStatus()` hook - `useSeasonStatus()` was never called in the Perps flow, only in Rewards **Result**: When users accessed Perps directly, `seasonId` was null � `useReferralDetails()` returned early � no referral code fetched � UI remained empty. Issue: https://consensyssoftware.atlassian.net/browse/TAT-1981 ### What is the improvement/solution? Added the missing `useSeasonStatus()` hook call to `PerpsHeroCardView.tsx` to ensure `seasonId` is populated before `useReferralDetails()` attempts to fetch. **Data flow after fix:** ``` PerpsHeroCardView mounts � useSeasonStatus() fetches season data � seasonId stored in Redux � useReferralDetails() now has seasonId � Fetches referral code successfully � Referral code displays in UI ``` **Key changes:** - Added `useSeasonStatus({ onlyForExplicitFetch: false })` before `useReferralDetails()` - Only 2 lines added (import + hook call) - Mirrors the approach used in `RewardsNavigator.tsx` (line 23) ## **Changelog** CHANGELOG entry: Fixed MetaMask referral code not displaying in Perps PnL card without first visiting Rewards page ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/TAT-1981 ## **Manual testing steps** ```gherkin Feature: Display referral code on Perps PnL Hero Card without Rewards prerequisite Scenario: Fresh app session - user accesses Perps directly without visiting Rewards Given user is opted into MetaMask Rewards And user has a referral code assigned (e.g., "MMCSI") And user has a fresh app session (no persisted Redux state) And user has NOT visited the Rewards section When user navigates directly to Perps tab And user opens an existing position And user taps the "Share" button to open PnL Hero Card Then the referral code should appear in the top-right corner And the referral code should be included in the share message And no errors should appear in console logs Scenario: Verify prerequisite data is fetched Given user is opted into MetaMask Rewards And app state is cleared (no cached seasonId) When user opens Perps Hero Card Then useSeasonStatus() should be called And seasonId should be populated in Redux state And useReferralDetails() should be called after seasonId is available And referral code should be fetched and displayed Scenario: Works consistently across multiple sessions Given user has referral code And user opens app multiple times When user goes directly to Perps (never visits Rewards) And opens PnL Hero Card in each session Then referral code displays correctly every time And no manual navigation to Rewards is required ``` ## **Screenshots/Recordings** ### **Before** PR MetaMask#22175 fixed the issue IF user visited Rewards first, but referral code remained missing when accessing Perps directly in a fresh session. **Root cause**: Missing `seasonId` dependency caused `useReferralDetails()` to return early without fetching. ### **After** Referral code now displays correctly in all scenarios: - � Fresh app install � directly to Perps � referral code shows - � Cleared app data � directly to Perps � referral code shows - � No requirement to visit Rewards page first - � Works consistently across sessions https://github.com/user-attachments/assets/aac690cc-aaa6-4b68-b2ca-26e162f401d0 ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --- ## Technical Implementation Details ### Root Cause Analysis **Why PR MetaMask#22175 was incomplete:** 1. **Added**: `useReferralDetails()` hook to PerpsHeroCardView 2. **Missing**: `useSeasonStatus()` hook (required prerequisite) **Dependency chain exposed by investigation:** ```typescript // useReferralDetails.ts - lines 24-28 if (!subscriptionId || !seasonId) { // �� Early exit if seasonId missing dispatch(setReferralDetailsError(false)); dispatch(setReferralDetailsLoading(false)); return; // NO FETCH HAPPENS } ``` **Where seasonId comes from:** - Only set by `setSeasonStatus` Redux action (reducers/rewards/index.ts:147) - Only dispatched by `useSeasonStatus()` hook (useSeasonStatus.ts:68) - `useSeasonStatus()` only called in `RewardsNavigator.tsx` (line 23) - **NEVER called in Perps flow** � seasonId remains null � fetch never happens ### Files Modified **Single file changed:** - `app/components/UI/Perps/Views/PerpsHeroCardView/PerpsHeroCardView.tsx` ### Code Changes **Added 2 lines:** ```typescript // Line 63: Import added import { useSeasonStatus } from '../../../Rewards/hooks/useSeasonStatus'; // Lines 92-93: Hook call added BEFORE useReferralDetails // Fetch season status to populate seasonId (required by useReferralDetails) useSeasonStatus({ onlyForExplicitFetch: false }); ``` ### Why This Fixes The Issue 1. **Prerequisite satisfied**: `useSeasonStatus()` populates `seasonId` in Redux 2. **Correct order**: Called before `useReferralDetails()` so dependency is available 3. **Same pattern**: Mirrors `RewardsNavigator.tsx` implementation (line 23) 4. **No race condition**: Both hooks use `useFocusEffect` which runs synchronously on mount 5. **Redux caching**: Once fetched, `seasonId` persists for session ### Data Flow Verification ``` PerpsHeroCardView mounts � useSeasonStatus({ onlyForExplicitFetch: false }) called � Fetches: RewardsController:getSeasonStatus � dispatch(setSeasonStatus({ season: { id: "123" } })) � Redux: state.rewards.seasonId = "123" � � useReferralDetails() called � Checks: subscriptionId � && seasonId � � Fetches: RewardsController:getReferralDetails � dispatch(setReferralDetails({ referralCode: "MMCSI" })) � useSelector(selectReferralCode) re-renders � Referral code displays in UI � ``` ### Testing Verification � **ESLint**: No errors � **TypeScript**: Types validated � **Code review**: Matches Rewards implementation pattern � **Dependency analysis**: All prerequisites satisfied ### Performance Impact - **Minimal overhead**: Single additional API call on Hero Card mount - **Cached**: Season data persists in Redux for session (no redundant fetches) - **Same cost as Rewards**: Uses identical hooks as Rewards section - **No extra renders**: Hooks run during mount phase ### Comparison with PR MetaMask#22175 | Aspect | PR MetaMask#22175 | This PR | |--------|-----------|---------| | Hooks added | `useReferralDetails()` | `useSeasonStatus()` + `useReferralDetails()` | | Lines changed | 2 | 4 | | Dependencies satisfied | L Missing seasonId | � All dependencies | | Works after Rewards visit | � Yes | � Yes | | Works on direct Perps access | L No | � Yes | | Works on fresh install | L No | � Yes | ### Related Code References - `useSeasonStatus` hook: `app/components/UI/Rewards/hooks/useSeasonStatus.ts` - `useReferralDetails` hook: `app/components/UI/Rewards/hooks/useReferralDetails.ts` - Rewards implementation: `app/components/UI/Rewards/RewardsNavigator.tsx:23` - Redux seasonId: `app/reducers/rewards/index.ts:147` - Redux referralCode: `app/reducers/rewards/selectors.ts:selectReferralCode` <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Integrates `useSeasonStatus` into `PerpsHeroCardView` to ensure referral code data loads without visiting Rewards, and updates tests to mock the hook. > > - **Perps**: > - `app/components/UI/Perps/Views/PerpsHeroCardView/PerpsHeroCardView.tsx` > - Import and call `useSeasonStatus({ onlyForExplicitFetch: false })` before `useReferralDetails()` to populate `seasonId` and load referral code for the PnL Hero Card and share message. > - **Tests**: > - `app/components/UI/Perps/Views/PerpsHeroCardView/PerpsHeroCardView.test.tsx` > - Add Jest mock for `../../../Rewards/hooks/useSeasonStatus`. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 14baca8. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
1 parent f19868c commit b23a0c7

2 files changed

Lines changed: 7 additions & 0 deletions

File tree

app/components/UI/Perps/Views/PerpsHeroCardView/PerpsHeroCardView.test.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,9 @@ jest.mock('../../../Rewards/utils', () => ({
9191
jest.mock('../../../Rewards/hooks/useReferralDetails', () => ({
9292
useReferralDetails: jest.fn(),
9393
}));
94+
jest.mock('../../../Rewards/hooks/useSeasonStatus', () => ({
95+
useSeasonStatus: jest.fn(),
96+
}));
9497
jest.mock('@metamask/design-tokens', () => ({
9598
brandColor: {
9699
black: '#000000',

app/components/UI/Perps/Views/PerpsHeroCardView/PerpsHeroCardView.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ import {
6060
getPerpsHeroCardViewSelector,
6161
} from '../../../../../../e2e/selectors/Perps/Perps.selectors';
6262
import { useReferralDetails } from '../../../Rewards/hooks/useReferralDetails';
63+
import { useSeasonStatus } from '../../../Rewards/hooks/useSeasonStatus';
6364
import { getPerpsDisplaySymbol } from '../../utils/marketUtils';
6465

6566
// To add a new card, add the image to the array.
@@ -88,6 +89,9 @@ const PerpsHeroCardView: React.FC = () => {
8889

8990
const rewardsReferralCode = useSelector(selectReferralCode);
9091

92+
// Fetch season status to populate seasonId (required by useReferralDetails)
93+
useSeasonStatus({ onlyForExplicitFetch: false });
94+
9195
// Fetch referral details to ensure code is available for display
9296
useReferralDetails();
9397

0 commit comments

Comments
 (0)