Commit ef84315
authored
feat(card): handle unauthenticated case on money account linkage (#30227)
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.
In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->
## **Description**
This branch improves the **Money Account → Card linkage** entry flow
when the user is **not** authenticated with the Card backend.
**Previous behaviour:** Link-card CTAs from Money Account effectively
sent unauthenticated users to Card home without completing auth or
resuming linkage.
**New behaviour:**
1. **Authenticated** — Unchanged: if requirements are met and the
account is not already delegated, open the linkage bottom sheet (still
requires `moneyAccountCardToken` when authenticated).
2. **Not authenticated, cardholder** — Set a Redux
`pendingMoneyAccountCardLink` flag, navigate into Card (`CARD.ROOT` →
`CARD.HOME` → `CARD.AUTHENTICATION`) with `showAuthPrompt: true` and a
`postAuthRedirect` payload (origin for future multi-entrypoint use).
After successful login, **`NavigationService.navigation.goBack()`** pops
the pushed `Card.ROOT` so the user returns to the tab they came from
(e.g. Money) **without** leaving `CardAuthentication` on the stack or
cross-navigating with a flicker. A `useEffect` in
[`useMoneyAccountCardLinkage`](app/components/UI/Card/hooks/useMoneyAccountCardLinkage.tsx)
resumes: waits for `cardHomeDataStatus` to reach `success` or `error`
before clearing the pending flag when `moneyAccountCardToken` is still
missing (avoids clearing too early while card home data loads
post-login); if delegated already, clears pending; if token is present,
opens the linkage sheet and clears pending.
3. **Not authenticated, not a cardholder** — Navigates to Card
onboarding root with `moneyAccountLinkIntent: true` (Spending-limit lock
for Money as spending source remains for a follow-up branch).
**What changed (high level):**
1. **Redux** —
[`app/core/redux/slices/card/index.ts`](app/core/redux/slices/card/index.ts):
`pendingMoneyAccountCardLink`, `setPendingMoneyAccountCardLink`,
`selectPendingMoneyAccountCardLink`.
2. **Hook** —
[`useMoneyAccountCardLinkage.tsx`](app/components/UI/Card/hooks/useMoneyAccountCardLinkage.tsx):
`startLinkFlow(origin)`, nested navigation for auth vs onboarding,
resume effect with `selectCardHomeDataStatus` gating.
3. **Money UI** —
[`MoneyHomeView.tsx`](app/components/UI/Money/Views/MoneyHomeView/MoneyHomeView.tsx):
link CTA calls `startLinkFlow` with root-level origin `{ screen:
Routes.MONEY.ROOT, params: { screen: Routes.MONEY.HOME } }`.
4. **Card auth** —
[`CardAuthentication.tsx`](app/components/UI/Card/Views/CardAuthentication/CardAuthentication.tsx):
optional route params `postAuthRedirect` / `showAuthPrompt`; on
successful login when `postAuthRedirect` is set, `goBack()` on the root
`NavigationService` instead of resetting to Card home or navigating to
Money by name.
### Why
- Cardholders who start linkage from Money need **auth first**, then
**the same bottom sheet** once delegation data is ready, without losing
context or leaving a stale auth screen on the stack when returning to
tabs.
- **`moneyAccountCardToken`** is unavailable until post-auth card data
loads; gating on **`cardHomeDataStatus`** avoids dropping the pending
flag during that window.
### What changed (scoped paths)
| Area | Files / behaviour |
| ---- | ----------------- |
| **Redux (card slice)** |
[`app/core/redux/slices/card/index.ts`](app/core/redux/slices/card/index.ts),
[`app/core/redux/slices/card/index.test.ts`](app/core/redux/slices/card/index.test.ts)
|
| **Linkage hook** |
[`app/components/UI/Card/hooks/useMoneyAccountCardLinkage.tsx`](app/components/UI/Card/hooks/useMoneyAccountCardLinkage.tsx),
[`.test.tsx`](app/components/UI/Card/hooks/useMoneyAccountCardLinkage.test.tsx)
|
| **Card login** |
[`app/components/UI/Card/Views/CardAuthentication/CardAuthentication.tsx`](app/components/UI/Card/Views/CardAuthentication/CardAuthentication.tsx),
[`.test.tsx`](app/components/UI/Card/Views/CardAuthentication/CardAuthentication.test.tsx)
|
| **Money home** |
[`app/components/UI/Money/Views/MoneyHomeView/MoneyHomeView.tsx`](app/components/UI/Money/Views/MoneyHomeView/MoneyHomeView.tsx),
[`.test.tsx`](app/components/UI/Money/Views/MoneyHomeView/MoneyHomeView.test.tsx)
|
### Out of scope (intentional)
- Onboarding branch: locking Money Account as spending source on
Spending Limit (`moneyAccountLinkIntent` wiring beyond navigation is
deferred).
## **Changelog**
CHANGELOG entry: Improved Money Account link-to-Card flow for
unauthenticated cardholders (auth screen, return to origin tab without
stale stack, resume linkage sheet after card data loads); added pending
linkage Redux flag and onboarding navigation intent for non-cardholders.
## **Related issues**
Fixes:
<!-- Add ticket ID(s), e.g. Fixes: MUSD-xxx or #12345 -->
## **Manual testing steps**
```gherkin
Feature: Money Account link card when not authenticated (cardholder)
Background:
Given Money Account is enabled and requirements for card linkage are met
And the user is a Card cardholder but not authenticated with the Card backend
Scenario: link card from Money home
When the user taps the link card CTA from Money Account home
Then they are taken to Card authentication with the auth prompt as configured
When the user completes login successfully
Then they return to Money Account (tab under the pushed Card stack is revealed)
And Card authentication is not left on the stack when re-opening the Card tab
When card home / delegation data has finished loading
Then the linkage bottom sheet opens if the Money account is not already delegated and a card token is available
Scenario: already delegated after login
When the user completes login and data shows the Money account is already delegated
Then the pending linkage flow clears without showing the sheet
Scenario: authenticated user
Given the user is already authenticated with Card
When they tap link card from Money home and are not already delegated
Then the linkage bottom sheet opens as before (no redirect to auth)
```
## **Screenshots/Recordings**
### **Before**
<!-- Unauthenticated: redirect to Card home only; no resume sheet;
possible stack flicker. -->
### **After**
<!-- Auth → back to Money tab → linkage sheet after data load; clean
Card tab stack. -->
## **Pre-merge author checklist**
<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.
Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->
- [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.
#### 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](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example
For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).
## **Pre-merge reviewer checklist**
<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->
- [ ] 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]
> **Medium Risk**
> Modifies cross-stack navigation and linkage orchestration using a new
Redux pending flag; main risk is regressions in navigation stack
behavior or incorrectly resuming/clearing the pending linkage state
after login.
>
> **Overview**
> Improves the Money Account → Card linkage entry flow for
unauthenticated users by introducing a `pendingMoneyAccountCardLink`
Redux flag and a new `startLinkFlow(origin)` API in
`useMoneyAccountCardLinkage` that routes users to Card auth/onboarding
and resumes opening the Link Card sheet after authentication.
>
> Updates `CardAuthentication` to accept an optional `postAuthRedirect`
param and, on successful login, pop `Card.ROOT` via
`NavigationService.navigation.goBack()` instead of resetting the inner
Card stack, preserving the originating tab’s navigation state.
>
> Refactors `MoneyHomeView` link-card CTAs to call `startLinkFlow`
(passing the Money home origin) and expands unit tests to cover the new
branching and resume behavior, including token-resolution and
data-loading edge cases.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
34bad9c. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->1 parent 7274b18 commit ef84315
8 files changed
Lines changed: 602 additions & 43 deletions
File tree
- app
- components/UI
- Card
- Views/CardAuthentication
- hooks
- Money/Views/MoneyHomeView
- core/redux/slices/card
Lines changed: 43 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
24 | 24 | | |
25 | 25 | | |
26 | 26 | | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
27 | 41 | | |
28 | 42 | | |
29 | 43 | | |
| |||
442 | 456 | | |
443 | 457 | | |
444 | 458 | | |
| 459 | + | |
| 460 | + | |
| 461 | + | |
| 462 | + | |
| 463 | + | |
| 464 | + | |
| 465 | + | |
| 466 | + | |
| 467 | + | |
| 468 | + | |
| 469 | + | |
| 470 | + | |
| 471 | + | |
| 472 | + | |
| 473 | + | |
| 474 | + | |
| 475 | + | |
| 476 | + | |
| 477 | + | |
| 478 | + | |
| 479 | + | |
| 480 | + | |
| 481 | + | |
| 482 | + | |
| 483 | + | |
| 484 | + | |
| 485 | + | |
| 486 | + | |
| 487 | + | |
445 | 488 | | |
446 | 489 | | |
447 | 490 | | |
| |||
Lines changed: 14 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
30 | 30 | | |
31 | 31 | | |
32 | 32 | | |
| 33 | + | |
33 | 34 | | |
34 | 35 | | |
35 | 36 | | |
| |||
41 | 42 | | |
42 | 43 | | |
43 | 44 | | |
44 | | - | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
45 | 51 | | |
46 | 52 | | |
47 | 53 | | |
| |||
51 | 57 | | |
52 | 58 | | |
53 | 59 | | |
| 60 | + | |
54 | 61 | | |
55 | 62 | | |
56 | 63 | | |
| |||
207 | 214 | | |
208 | 215 | | |
209 | 216 | | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
210 | 222 | | |
211 | 223 | | |
212 | 224 | | |
| |||
228 | 240 | | |
229 | 241 | | |
230 | 242 | | |
| 243 | + | |
231 | 244 | | |
232 | 245 | | |
233 | 246 | | |
| |||
0 commit comments