Skip to content

feat(rewards): add deeplinks for campaigns & musd pages#28802

Merged
VGR-GIT merged 14 commits intomainfrom
rwds-1152-deeplinks-campaigns
Apr 16, 2026
Merged

feat(rewards): add deeplinks for campaigns & musd pages#28802
VGR-GIT merged 14 commits intomainfrom
rwds-1152-deeplinks-campaigns

Conversation

@VGR-GIT
Copy link
Copy Markdown
Contributor

@VGR-GIT VGR-GIT commented Apr 14, 2026

Description

Extends the /rewards deeplink handler to support ?page= and ?campaign= query params, enabling deep navigation to specific pages within the Rewards flow.

Jira: https://consensyssoftware.atlassian.net/browse/RWDS-1152

New deeplinks

URL Destination
/rewards?page=campaigns Campaigns page
/rewards?campaign=ondo Ondo campaign details
/rewards?campaign=season1 Season 1 campaign details
/rewards?page=musd mUSD bonus calculator

Behaviour

  • Subscribed users: deeplink routes directly to the requested page
  • Non-subscribed users: deeplink still routes through onboarding first (unchanged behaviour)
  • No page/campaign param: existing behaviour preserved (navigates to REWARDS_VIEW, then dashboard or onboarding)
  • Unknown param value: falls through to default navigation (no crash)

Changelog

CHANGELOG entry: new reward campaign deeplinks + musd

Checklist

  • Tests written for all new deeplink params
  • ESLint passes (no warnings)
  • Prettier passes (no formatting changes)
  • Existing tests still pass

🤖 Generated with Claude Code


Note

Medium Risk
Changes core navigation behavior for subscribed Rewards users and introduces new persisted state, so regressions could misroute users or loop navigations despite added tests and guards.

Overview
Adds support for /rewards deeplinks with ?page= and ?campaign= query params by persisting a pendingDeeplink intent in the rewards Redux slice, so navigation survives UnmountOnBlur remounts.

Updates RewardsNavigator to consume pendingDeeplink for subscribed users (routing to campaigns, Ondo/Season 1 details, mUSD calculator, or benefits) and then clear the intent with a one-shot useRef guard to prevent a follow-up effect from overriding the deeplink with a dashboard navigation.

Adjusts campaign detail screens to tolerate missing campaignId route params (deeplink entry) by resolving the campaign by CampaignType, and updates useOndoAccountPicker to accept an optional campaign id. Test coverage is expanded across the deeplink handler, navigator routing/clearing behavior, and some view test stubbing to avoid deep import dependencies.

Reviewed by Cursor Bugbot for commit 748afe7. Bugbot is set up for automated code reviews on this repo. Configure here.

@VGR-GIT VGR-GIT requested review from a team as code owners April 14, 2026 11:16
@github-actions
Copy link
Copy Markdown
Contributor

CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes.

@metamaskbot metamaskbot added the team-rewards Rewards team label Apr 14, 2026
@github-actions github-actions bot added size-M risk-low Low testing needed · Low bug introduction risk labels Apr 14, 2026
@metamaskbot metamaskbot added the INVALID-PR-TEMPLATE PR's body doesn't match template label Apr 14, 2026
Comment thread app/components/UI/Rewards/Views/BenefitsView/BenefitsView.test.tsx Outdated
@github-actions github-actions bot added risk-low Low testing needed · Low bug introduction risk and removed risk-low Low testing needed · Low bug introduction risk labels Apr 14, 2026
Comment thread app/components/UI/Rewards/RewardsNavigator.tsx
@VGR-GIT VGR-GIT force-pushed the rwds-1152-deeplinks-campaigns branch from ac0fcd5 to d343624 Compare April 14, 2026 12:41
@github-actions github-actions bot added risk-low Low testing needed · Low bug introduction risk and removed risk-low Low testing needed · Low bug introduction risk labels Apr 14, 2026
Comment thread app/components/UI/Rewards/RewardsNavigator.tsx Outdated
@VGR-GIT
Copy link
Copy Markdown
Contributor Author

VGR-GIT commented Apr 14, 2026

Beep boop, claude here for Rik Van Gulck; @sophieqgu heads up — there is a known limitation with the current deeplink routing implementation:

Known limitation: If a user opens a deeplink targeting a Rewards sub-view (e.g., ?campaign=ondo, ?campaign=season1, ?page=musd, etc.) while they are already inside the Rewards feature, they will remain on their current screen instead of being navigated to the target.

Why it happens: RewardsNavigator reads the pending deeplink from Redux on mount (via a useEffect that fires when the component mounts or when pendingDeeplink changes). If the navigator is already mounted (user is already in Rewards), the deeplink is consumed and navigate() is called — but since the user is already nested inside a sub-screen, the navigation may not have the intended effect (e.g., they could end up at the dashboard instead of the target screen).

The plain ?referral=... deeplink (no sub-screen) works correctly in all cases since it only needs to open the Rewards tab.

This is a future follow-up; the current implementation already covers the primary use case (user is on a different tab when the deeplink is opened).

@github-actions github-actions bot added risk-low Low testing needed · Low bug introduction risk and removed risk-low Low testing needed · Low bug introduction risk labels Apr 14, 2026
Comment thread app/core/DeeplinkManager/handlers/legacy/handleRewardsUrl.ts
@github-actions github-actions bot added risk-medium Moderate testing recommended · Possible bug introduction risk and removed risk-low Low testing needed · Low bug introduction risk labels Apr 14, 2026
sophieqgu
sophieqgu previously approved these changes Apr 14, 2026
@github-project-automation github-project-automation bot moved this to Needs dev review in PR review queue Apr 14, 2026
@sophieqgu sophieqgu moved this from Needs dev review to Has approvals, needs CODEOWNER in PR review queue Apr 14, 2026
Comment thread app/components/UI/Rewards/RewardsNavigator.tsx
Comment thread app/components/UI/Rewards/Views/OndoCampaignDetailsView.tsx Outdated
@github-actions github-actions bot added risk-low Low testing needed · Low bug introduction risk and removed risk-low Low testing needed · Low bug introduction risk labels Apr 16, 2026
@github-actions github-actions bot added size-L risk-low Low testing needed · Low bug introduction risk and removed size-M risk-low Low testing needed · Low bug introduction risk labels Apr 16, 2026
jbblanc
jbblanc previously approved these changes Apr 16, 2026
EugeniyBykov
EugeniyBykov previously approved these changes Apr 16, 2026
Comment thread app/components/UI/Rewards/Views/SeasonOneCampaignDetailsView.tsx
The 481803c commit re-introduced `pendingSheetPosition={leaderboardPendingSheetPosition}`
to OndoLeaderboard's JSX, but `leaderboardPendingSheetPosition` was
removed by the prior "remove pending sheet" commit and OndoLeaderboard
no longer accepts this prop. This caused a ReferenceError in every
test that rendered the leaderboard section.

Component fix:
- Remove the stale `pendingSheetPosition` prop from OndoLeaderboard

Test fixes:
- Mock useOndoAccountPicker (breaks @tanstack/react-query import chain)
  with a stateful implementation so the account-picker sheet tests work
- Mock useAnalytics and core/Analytics (break store/DeeplinkManager
  import chain triggered by OndoCampaignCTA)
- Fix useTailwind mock to return a callable function (Box uses tagged
  template literals tw`...`)
- Stub Skeleton which is absent from the installed design-system version

Co-authored-by: VGR-GIT <vangulckrik@gmail.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
@VGR-GIT VGR-GIT dismissed stale reviews from EugeniyBykov and jbblanc via 2289729 April 16, 2026 08:34
@github-actions github-actions bot added risk-low Low testing needed · Low bug introduction risk and removed risk-low Low testing needed · Low bug introduction risk labels Apr 16, 2026
Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 2289729. Configure here.


// Pending deeplink navigation intent, stored in Redux so it survives the
// UnmountOnBlur remount of RewardsHome when navigating from outside the tab.
pendingDeeplink: PendingDeeplink | null;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale persisted deeplink causes unexpected navigation on revisit

Medium Severity

The pendingDeeplink field is part of RewardsState which is persisted and rehydrated across app restarts. Once set, it's only cleared in two places: inside handleRewardsUrl (when no page/campaign param) and inside the RewardsNavigator useEffect (after successful consumption). If the deeplink is set but never consumed — e.g., a non-subscribed user opens a deeplink, reaches onboarding, abandons it, then later returns to rewards via the tab bar (TabBar.tsx navigates directly to REWARDS_VIEW without calling handleRewardsUrl) — the stale pendingDeeplink persists in Redux and triggers unexpected navigation to the old deeplink target. This stale state also survives app restarts via rehydration.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 2289729. Configure here.

Co-authored-by: VGR-GIT <vangulckrik@gmail.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions github-actions bot added risk-medium Moderate testing recommended · Possible bug introduction risk and removed risk-low Low testing needed · Low bug introduction risk labels Apr 16, 2026
Replace direct useState import reference in mock factory with
jest.requireActual('react').useState to comply with Jest's hoisting
restrictions on out-of-scope variables in mock factories.

Co-authored-by: VGR-GIT <vangulckrik@gmail.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions github-actions bot added risk-medium Moderate testing recommended · Possible bug introduction risk and removed risk-medium Moderate testing recommended · Possible bug introduction risk labels Apr 16, 2026
@github-actions
Copy link
Copy Markdown
Contributor

🔍 Smart E2E Test Selection

  • Selected E2E tags: SmokeWalletPlatform
  • Selected Performance tags: None (no tests recommended)
  • Risk Level: medium
  • AI Confidence: 72%
click to see 🤖 AI reasoning details

E2E Test Selection:
The changes are entirely within the Rewards feature: deeplink URL parsing (handleRewardsUrl.ts), Redux state for pending deeplinks (rewards reducer/selectors), RewardsNavigator deeplink routing logic, and campaign detail views (OndoCampaignDetailsView, SeasonOneCampaignDetailsView) that now support optional campaignId for deeplink scenarios.

No dedicated Rewards E2E test tag exists. The closest coverage is SmokeWalletPlatform, which includes the musd-conversion-happy-path.spec.ts test that exercises the mUSD/Rewards flow. This test uses the SmokeWalletPlatform tag and validates the Rewards ecosystem.

The changes do NOT affect:

  • Shared navigation components (TabBar, modals, confirmations)
  • Account management, identity, network, or trading flows
  • Any other feature area outside Rewards

Risk is medium because:

  • The Redux state change (adding pendingDeeplink) could affect reducer rehydration or state shape
  • The RewardsNavigator effect logic with skipNextEffectRef is a subtle timing fix that could have edge cases
  • The optional campaignId in campaign detail views changes component behavior for deeplink entry points
  • However, the changes are well-scoped to the Rewards feature with no cross-cutting impact

Confidence is 72 because there are no dedicated Rewards E2E tests, so coverage is indirect through SmokeWalletPlatform's mUSD tests.

Performance Test Selection:
No performance-sensitive changes. The modifications are limited to deeplink URL parsing, Redux state additions (a simple null/object field), and navigation routing logic in RewardsNavigator. No list rendering, heavy computation, startup initialization, or UI rendering performance concerns are introduced.

View GitHub Actions results

@github-actions
Copy link
Copy Markdown
Contributor

E2E Fixture Validation — Schema is up to date
11 value mismatches detected (expected — fixture represents an existing user).
View details

@sonarqubecloud
Copy link
Copy Markdown

@github-project-automation github-project-automation bot moved this from Has approvals, needs CODEOWNER to Review finalised - Ready to be merged in PR review queue Apr 16, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

INVALID-PR-TEMPLATE PR's body doesn't match template release-7.74.0 Issue or pull request that will be included in release 7.74.0 risk-medium Moderate testing recommended · Possible bug introduction risk size-L team-rewards Rewards team

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

7 participants