Skip to content

feat: show RewardsVipBadge in swap page#30410

Merged
micaelae merged 11 commits into
mainfrom
swaps4483-vip-badge
May 21, 2026
Merged

feat: show RewardsVipBadge in swap page#30410
micaelae merged 11 commits into
mainfrom
swaps4483-vip-badge

Conversation

@micaelae

@micaelae micaelae commented May 19, 2026

Copy link
Copy Markdown
Member

Description

Changes

  • Expose getVipTierForAccount from rewards controller
  • implement RewardsVipBadge component, which fetches the account's vipTier and displays it
  • Update Bridge page disclaimers to reflect discounted fees

Changelog

CHANGELOG entry: feat: show RewardsVipBadge in swap page

Related issues

Fixes: https://consensyssoftware.atlassian.net/browse/SWAPS-4465

Manual testing steps

Feature: rewards vip badge

  Scenario: user is in the VIP program
    Given they request a swap quote

    When user receives a quote
    Then they see the VIP badge and their discounted MM fee

  Scenario: user is not in the VIP program
    Given they request a swap quote

    When user receives a quote
    Then they don't see the VIP badge

Screenshots/Recordings

Before

After

Screenshot 2026-05-19 at 2 54 41 PM Screenshot 2026-05-19 at 2 54 50 PM Screenshot 2026-05-19 at 2 55 05 PM

Pre-merge author checklist

Performance checks (if applicable)

  • I've tested on Android
    • Ideally on a mid-range device; emulator is acceptable
  • I've tested with a power user scenario
    • Use these power-user SRPs to import wallets with many accounts and tokens
  • I've instrumented key operations with Sentry traces for production performance metrics

For performance guidelines and tooling, see the Performance Guide.

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.

Note

Medium Risk
Touches fee-disclaimer logic in the Bridge confirmation flow and adds a new RewardsController API that calls /vip/fees, which could affect pricing/UX if the quote fee fields or VIP lookup behave unexpectedly.

Overview
Bridge footer now surfaces VIP fee discounts. A new useFeeDisclaimer hook derives the disclaimer copy from quote baseBpsFee vs quoteBpsFee, and BridgeViewFooter renders a struck-through base fee plus discounted fee text when applicable.

Adds a reusable VIP badge and controller support. Introduces RewardsVipBadge (and tests) that fetches and displays the account VIP tier, exports formatAccountToCaipAccountId for CAIP formatting, and adds RewardsController.getVipTierForAccount (with shared VIP fees fetch/dedup refactor + action type wiring) to support the badge.

Also updates selectors/testIDs and i18n strings to support the new disclaimer/badge and adjusts unit tests for discounted/undefined-fee cases.

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

@metamaskbotv2 metamaskbotv2 Bot added the team-swaps-and-bridge Swaps and Bridge team label May 19, 2026
@codecov-commenter

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 41.26984% with 37 lines in your changes missing coverage. Please review.
✅ Project coverage is 82.01%. Comparing base (c0d4af2) to head (f1338bb).
⚠️ Report is 41 commits behind head on main.

Files with missing lines Patch % Lines
...ontrollers/rewards-controller/RewardsController.ts 0.00% 28 Missing ⚠️
app/components/UI/Bridge/hooks/useFeeDisclaimer.ts 68.42% 2 Missing and 4 partials ⚠️
...ts/UI/Bridge/Views/BridgeView/BridgeViewFooter.tsx 40.00% 0 Missing and 3 partials ⚠️
Additional details and impacted files
@@           Coverage Diff            @@
##             main   #30410    +/-   ##
========================================
  Coverage   82.01%   82.01%            
========================================
  Files        5444     5457    +13     
  Lines      145478   145939   +461     
  Branches    33292    33448   +156     
========================================
+ Hits       119307   119696   +389     
- Misses      18018    18050    +32     
- Partials     8153     8193    +40     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions github-actions Bot added size-L and removed size-M labels May 19, 2026
@micaelae micaelae marked this pull request as ready for review May 19, 2026 23:32
@micaelae micaelae requested review from a team as code owners May 19, 2026 23:32
Comment thread app/components/UI/Bridge/hooks/useFeeDisclaimer.ts Outdated
Comment thread app/components/UI/Bridge/Views/BridgeView/BridgeViewFooter.tsx
@micaelae micaelae enabled auto-merge May 20, 2026 00:13
@github-actions

Copy link
Copy Markdown
Contributor

🔍 Smart E2E Test Selection

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

E2E Test Selection:
The changes in this PR primarily affect:

  1. Bridge/Swap UI (BridgeViewFooter): The fee disclaimer section has been significantly restructured - it now uses a new useFeeDisclaimer hook and conditionally shows a RewardsVipBadge component. The approval tooltip has been moved into a separate Box with a new test ID (APPROVAL_TOOLTIP). This directly impacts the bridge flow UI that SmokeSwap tests exercise.

  2. RewardsController: A new getVipTierForAccount method was added and the VIP fees fetching logic was refactored into a shared private #getVipFeesForSubscriptionId method. The getPerpsDiscountForAccount method now uses this shared method. This refactoring could affect Perps fee discount behavior (SmokePerps).

  3. New RewardsVipBadge component: Displayed in the BridgeViewFooter when a user has VIP status - new UI element in the swap/bridge flow.

  4. New useFeeDisclaimer hook: Extracted fee disclaimer logic with new behavior for discounted fees (VIP users see different text).

  5. Locales: New strings added for VIP badge and fee display.

Tag selection rationale:

  • SmokeSwap: Direct impact on BridgeViewFooter UI which is part of the bridge/swap flow. The fee disclaimer text structure changed (now split into infoText, baseFeePercentage, infoSuffix). Existing tests checking fee disclaimer text may be affected.
  • SmokeConfirmations: Required alongside SmokeSwap per tag description (swap/bridge flows require confirmations).
  • SmokePerps: The RewardsController refactoring affects getPerpsDiscountForAccount which now uses the shared #getVipFeesForSubscriptionId. The VIP fee calculation logic changed (caching of vipPerpsFees state now happens in getPerpsDiscountForAccount rather than in the shared method). This could affect perps fee discount behavior.
  • SmokeWalletPlatform: Required alongside SmokePerps per tag description.

The QuoteView.selectors.ts still references fee_disclaimer from en.json which remains unchanged, so the existing fee disclaimer text selector should still work. However, the UI structure around it changed significantly.

Performance Test Selection:
The changes are focused on UI component additions (RewardsVipBadge, useFeeDisclaimer hook) and a controller method addition (getVipTierForAccount). These are not performance-critical paths - the VIP badge is only shown conditionally for VIP users, and the fee disclaimer restructuring is a UI-only change. No performance-sensitive areas like account list rendering, app startup, login flows, or heavy data loading are affected.

View GitHub Actions results

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

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 e1754ee. Configure here.

activeQuote &&
Boolean(baseBpsFee) &&
Boolean(quoteBpsFee) &&
baseBpsFee > quoteBpsFee;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Boolean() conflates zero with absent in discount check

Medium Severity

The isDiscounted check uses Boolean(quoteBpsFee) to verify the value exists, but Boolean(0) returns false. If a VIP user receives a 100% fee reduction (quoteBpsFee is 0 while baseBpsFee is positive), the discount is real but isDiscounted evaluates to false — hiding the VIP badge and strikethrough UI. The code already uses isNullOrUndefined (imported and applied on lines 23 and 29) to correctly distinguish 0 from null/undefined for the fee percentage calculations; the same approach fits here for consistency and correctness.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit e1754ee. Configure here.

@sonarqubecloud

Copy link
Copy Markdown

@micaelae micaelae added this pull request to the merge queue May 21, 2026
Merged via the queue into main with commit 381269b May 21, 2026
198 of 200 checks passed
@micaelae micaelae deleted the swaps4483-vip-badge branch May 21, 2026 08:50
@github-actions github-actions Bot locked and limited conversation to collaborators May 21, 2026
@metamaskbotv2 metamaskbotv2 Bot added the release-7.79.0 Issue or pull request that will be included in release 7.79.0 label May 21, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

release-7.79.0 Issue or pull request that will be included in release 7.79.0 size-L team-swaps-and-bridge Swaps and Bridge team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants