Commit ffc2566
authored
feat(card): Onboarding deep link (MetaMask#24042)
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->
## **Description**
<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->
### Reason for the change
We need to add a new deeplink (`card-onboarding`) to allow marketing
campaigns and external sources to direct users to the MetaMask Card
onboarding flow. This deeplink intelligently routes users based on their
card status.
### What's included
**1. New `card-onboarding` deeplink handler**
- Adds new deeplink action `CARD_ONBOARDING` supporting URLs like:
- `https://link.metamask.io/card-onboarding`
- `https://metamask.app.link/card-onboarding`
- Smart routing based on user state:
- **Authenticated or has card-linked account**: Switches to first
cardholder account → navigates to CardHome → shows toast notification
- **Not authenticated and no card-linked account**: Navigates to
CardWelcome (onboarding screen)
- Respects feature flags and geo-location restrictions before enabling
- Dispatches `setAlwaysShowCardButton(true)` to ensure card button
visibility
- Full analytics tracking with `CARD_ONBOARDING_DEEPLINK` event
**2. CardHome toast notification**
- Adds route params support (`showDeeplinkToast`) to display a toast
when user arrives via deeplink
- Shows "You already have a MetaMask Card linked to this account"
message
**3. CardButton simplification**
- Removes the "New" badge wrapper from the CardButton component
- Simplifies the component by removing badge-related logic and state
management
## **Changelog**
<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`
If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`
(This helps the Release Engineer do their job more quickly and
accurately)
-->
CHANGELOG entry: Added new card-onboarding deeplink to navigate users to
the MetaMask Card feature
## **Related issues**
Fixes:
## **Manual testing steps**
```gherkin
Feature: Card Onboarding Deeplink
Scenario: Authenticated user with card-linked account opens deeplink
Given user has the MetaMask app installed
And user is authenticated with the Card feature
And user has a card-linked account
When user opens the card-onboarding deeplink
Then app switches to the first cardholder account
And user is navigated to the Card Home screen
And a toast notification is displayed saying "You already have a MetaMask Card linked to this account"
Scenario: Authenticated user without card-linked account opens deeplink
Given user has the MetaMask app installed
And user is authenticated with the Card feature
And user has no card-linked account
When user opens the card-onboarding deeplink
Then user is navigated to the Card Home screen
And a toast notification is displayed
Scenario: Unauthenticated user without card opens deeplink
Given user has the MetaMask app installed
And user is not authenticated with the Card feature
And user has no card-linked account
When user opens the card-onboarding deeplink
Then user is navigated to the Card Welcome screen
And no toast notification is displayed
Scenario: User in unsupported region opens deeplink
Given user has the MetaMask app installed
And user is in an unsupported region
And card experimental switch is disabled
When user opens the card-onboarding deeplink
Then nothing happens (deeplink is ignored)
Scenario: Card button is always shown after deeplink
Given user has opened the card-onboarding deeplink
When user navigates to the wallet home screen
Then the card button is visible in the header
```
## **Screenshots/Recordings**
<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->
### **Before**
<!-- [screenshots/recordings] -->
### **After**
<!-- [screenshots/recordings] -->
## **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.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Adds a `card-onboarding` deeplink that conditionally enables Card,
navigates to the right Card screen (and switches to a card-linked
account), shows a toast on `CardHome`, and tracks analytics; updates
gating logic, caching behavior, routes, and tests.
>
> - **Deeplink & Navigation**:
> - Add `ACTIONS.CARD_ONBOARDING` and whitelist it in universal link
handling.
> - Implement `handleCardOnboarding` with feature-flag/geo checks,
optional account switch to first cardholder, navigation to
`CardHome`/`CardWelcome`, and analytics tracking.
> - Extend `Routes.CARD` (e.g., `CARD_MAIN_ROUTES`).
> - **CardHome**:
> - Add route param support via `useRoute` and show toast
(`showDeeplinkToast`) when navigated from deeplink.
> - Minor test refactors for auth-error cases and rerender logic.
> - **Gating & Hooks**:
> - Enhance `useIsBaanxLoginEnabled` to consider `cardGeoLocation` and
`cardSupportedCountries` (with pure helper).
> - Update `useGetDelegationSettings` caching to include `fetchOnMount`
(auth-aware).
> - **Analytics & Metrics**:
> - Add `MetaMetricsEvents.CARD_ONBOARDING_DEEPLINK` and
`CardDeeplinkActions`.
> - **Constants & i18n**:
> - Update deeplink constants/prefixes;
> - Add string `card.card_button_already_enabled_toast`.
> - **Tests**:
> - Comprehensive tests for deeplink handler, gating logic, and updated
hooks/components.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
ef3a4bf. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->1 parent 5b18690 commit ffc2566
14 files changed
Lines changed: 1090 additions & 86 deletions
File tree
- app
- components/UI/Card
- Views/CardHome
- hooks
- util
- constants
- core
- Analytics
- DeeplinkManager/handlers/legacy
- __tests__
- locales/languages
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
43 | 43 | | |
44 | 44 | | |
45 | 45 | | |
46 | | - | |
47 | | - | |
48 | | - | |
| 46 | + | |
49 | 47 | | |
50 | 48 | | |
51 | 49 | | |
| |||
2497 | 2495 | | |
2498 | 2496 | | |
2499 | 2497 | | |
2500 | | - | |
| 2498 | + | |
2501 | 2499 | | |
2502 | 2500 | | |
2503 | 2501 | | |
| |||
2510 | 2508 | | |
2511 | 2509 | | |
2512 | 2510 | | |
2513 | | - | |
2514 | 2511 | | |
2515 | 2512 | | |
2516 | 2513 | | |
| |||
2519 | 2516 | | |
2520 | 2517 | | |
2521 | 2518 | | |
2522 | | - | |
| 2519 | + | |
2523 | 2520 | | |
2524 | 2521 | | |
2525 | 2522 | | |
| |||
2532 | 2529 | | |
2533 | 2530 | | |
2534 | 2531 | | |
2535 | | - | |
2536 | 2532 | | |
2537 | 2533 | | |
2538 | 2534 | | |
2539 | 2535 | | |
2540 | 2536 | | |
2541 | | - | |
| 2537 | + | |
2542 | 2538 | | |
2543 | 2539 | | |
2544 | 2540 | | |
| |||
2551 | 2547 | | |
2552 | 2548 | | |
2553 | 2549 | | |
2554 | | - | |
2555 | 2550 | | |
2556 | 2551 | | |
2557 | 2552 | | |
| |||
2668 | 2663 | | |
2669 | 2664 | | |
2670 | 2665 | | |
2671 | | - | |
2672 | 2666 | | |
| 2667 | + | |
2673 | 2668 | | |
2674 | 2669 | | |
2675 | 2670 | | |
| |||
2684 | 2679 | | |
2685 | 2680 | | |
2686 | 2681 | | |
2687 | | - | |
2688 | | - | |
2689 | | - | |
2690 | | - | |
2691 | | - | |
2692 | | - | |
2693 | | - | |
2694 | | - | |
| 2682 | + | |
| 2683 | + | |
2695 | 2684 | | |
2696 | 2685 | | |
2697 | 2686 | | |
2698 | 2687 | | |
2699 | 2688 | | |
2700 | | - | |
2701 | | - | |
2702 | | - | |
2703 | | - | |
2704 | | - | |
2705 | | - | |
2706 | | - | |
2707 | | - | |
2708 | 2689 | | |
2709 | 2690 | | |
2710 | 2691 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
23 | 23 | | |
24 | 24 | | |
25 | 25 | | |
26 | | - | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
27 | 32 | | |
28 | 33 | | |
29 | 34 | | |
| |||
87 | 92 | | |
88 | 93 | | |
89 | 94 | | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
90 | 102 | | |
91 | 103 | | |
92 | 104 | | |
| |||
111 | 123 | | |
112 | 124 | | |
113 | 125 | | |
| 126 | + | |
114 | 127 | | |
115 | 128 | | |
116 | 129 | | |
117 | 130 | | |
118 | 131 | | |
| 132 | + | |
| 133 | + | |
119 | 134 | | |
120 | 135 | | |
121 | 136 | | |
| |||
260 | 275 | | |
261 | 276 | | |
262 | 277 | | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
263 | 297 | | |
264 | 298 | | |
265 | 299 | | |
| |||
0 commit comments