Commit dd7eb4b
chore(runway): cherry-pick fix(card): update feature flag listener on CardController (#29376)
- fix(card): update feature flag listener on CardController (#29350)
<!--
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 refreshes **card home data and Baanx configuration** when
**remote card feature flags** change, and fixes a **race** where a slow
**unauthenticated** `fetchCardHomeData` could overwrite state **after**
successful **submitCredentials**.
**Feature flags**
-
[`app/selectors/featureFlagController/card/index.ts`](app/selectors/featureFlagController/card/index.ts):
exports **`defaultCardFeatureFlag`** and **`resolveCardFeatureFlag`**
(empty remote payload → defaults). **`selectCardFeatureFlag`** now uses
**`resolveCardFeatureFlag`** so the same resolution rules apply in Redux
selectors and Engine.
**BaanxProvider / init**
-
[`BaanxProvider.ts`](app/core/Engine/controllers/card-controller/providers/BaanxProvider.ts):
accepts optional **`getCardFeatureFlag`** (lazy) in addition to legacy
**`cardFeatureFlag`**. A private getter resolves **`cardFeatureFlag`**
on each read so URLs/constants track the latest remote flags without
recreating the provider.
-
[`card-controller/index.ts`](app/core/Engine/controllers/card-controller/index.ts):
passes **`getCardFeatureFlag`** from
**`RemoteFeatureFlagController:getState`** +
**`resolveCardFeatureFlag`** into **`BaanxProvider`**.
**CardController**
- Subscribes to **`RemoteFeatureFlagController:stateChange`** with a
**selector** that serializes **`remoteFeatureFlags.cardFeature`** so
only meaningful card-flag updates run the handler.
- **`#handleCardFeatureFlagChange`**: if an EVM address is selected,
**`invalidateFetch()`**, clears **`cardHomeData`** / sets
**`cardHomeDataStatus`** to **`idle`**, then refetches card home data.
- **`#fetchCardHomeDataWithLogging`**: centralizes
**`fetchCardHomeData`** + **`Logger.error`** for account switch,
feature-flag refresh, **`submitCredentials`**, and
**`validateAndRefreshSession`**.
- **`#triggerCardholderCheck`** (accounts API URL path): uses
**`resolveCardFeatureFlag`** instead of ad-hoc casting.
- **`submitCredentials`**: sets **`cardHomeData`** to **`null`** and
status **`idle`**, calls **`invalidateFetch()`**, then fetches—so
in-flight unauthenticated responses cannot win over authenticated data.
**Messenger / types**
-
[`card-controller-messenger/index.ts`](app/core/Engine/messengers/card-controller-messenger/index.ts):
allows event **`RemoteFeatureFlagController:stateChange`**.
- [`types.ts`](app/core/Engine/controllers/card-controller/types.ts):
**`CardControllerAllowedEvents`** includes
**`RemoteFeatureFlagControllerStateChangeEvent`**.
**Tests**
-
[`CardController.test.ts`](app/core/Engine/controllers/card-controller/CardController.test.ts):
subscription to remote feature-flag state; handler clears state and
refetches; **`drops in-flight unauthenticated card home data after
successful auth`**.
-
[`BaanxProvider.test.ts`](app/core/Engine/controllers/card-controller/providers/BaanxProvider.test.ts):
**`getCardFeatureFlag`** read **lazily** during **`getOnChainAssets`**.
## **Changelog**
CHANGELOG entry: Card — **`CardController`** listens for
**`RemoteFeatureFlagController:stateChange`** and refetches card home
data when **`cardFeature`** changes; **`BaanxProvider`** resolves card
feature flags lazily; shared **`resolveCardFeatureFlag`**;
**`submitCredentials`** invalidates in-flight fetches and resets card
home state to avoid stale unauthenticated data after login.
## **Related issues**
Fixes: #29348
<!-- Add GitHub issue link when available, e.g. Fixes #12345 -->
## **Manual testing steps**
```gherkin
Feature: Card home and Baanx flags stay in sync with remote card feature flags
Scenario: Remote card feature flag updates while card tab is open
Given the user is on an EVM account with card session and card home loaded
When remote `cardFeature` changes (e.g. rollout or config update)
Then card home data is cleared to idle and refetched
And Baanx-backed calls use the updated flag-derived config on subsequent requests
Scenario: Login while an unauthenticated card home fetch is still in flight
Given an unauthenticated card home fetch has not completed
When the user completes submitCredentials successfully
Then authenticated card home data wins and a late unauthenticated response does not overwrite it
Scenario: Card feature flag change with no selected EVM address
When RemoteFeatureFlagController emits a card-related change but no EVM address is selected
Then the handler returns early without refetch errors
```
## **Screenshots/Recordings**
<!-- Optional: behavior is mostly data-layer; attach if you verify on
device after a forced remote flag change. -->
### **Before**
<!-- Card home could stay stale until manual refresh; rare stale data
after fast login during slow unauthenticated fetch. -->
### **After**
<!-- Card home refetches when `cardFeature` changes; submitCredentials
path drops stale in-flight unauthenticated results. -->
## **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 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**
> Updates card state refresh triggers and fetch invalidation logic
around auth and feature-flag changes; risk is moderate due to new event
subscriptions and potential for extra network calls or missed updates if
selectors are wrong.
>
> **Overview**
> **Card home data now refreshes when remote `cardFeature` flags
change.** `CardController` subscribes to
`RemoteFeatureFlagController:stateChange`, clears `cardHomeData`/status
back to `idle`, invalidates any in-flight fetch, and refetches.
>
> **Fixes a race where slow unauthenticated fetches could overwrite
authenticated state.** After successful `submitCredentials`, the
controller resets home data, bumps the fetch generation, and refetches
via a shared `#fetchCardHomeDataWithLogging` helper (also used by
account-switch and session refresh paths).
>
> **Feature-flag resolution and consumption were tightened.** Adds
`resolveCardFeatureFlag` (and exports `defaultCardFeatureFlag`) to
normalize empty remote payloads to defaults; `BaanxProvider` can now
read flags lazily via a `getCardFeatureFlag` callback wired in
`cardControllerInit`, and the card-controller messenger/types allow the
new remote-flag stateChange event.
>
> Tests add coverage for the new subscription behavior, the stale-fetch
drop after auth, and lazy flag reads in `BaanxProvider`.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
0d9863b. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
[890ac4a](890ac4a)
Co-authored-by: Bruno Nascimento <brunonascimentodev@gmail.com>1 parent dbab42c commit dd7eb4b
8 files changed
Lines changed: 225 additions & 45 deletions
File tree
- app
- core/Engine
- controllers/card-controller
- providers
- messengers/card-controller-messenger
- selectors/featureFlagController/card
Lines changed: 111 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 | + | |
27 | 33 | | |
28 | 34 | | |
29 | 35 | | |
| |||
314 | 320 | | |
315 | 321 | | |
316 | 322 | | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
| 361 | + | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
| 367 | + | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
| 375 | + | |
| 376 | + | |
| 377 | + | |
| 378 | + | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
| 382 | + | |
| 383 | + | |
| 384 | + | |
| 385 | + | |
| 386 | + | |
| 387 | + | |
317 | 388 | | |
318 | 389 | | |
319 | 390 | | |
| |||
646 | 717 | | |
647 | 718 | | |
648 | 719 | | |
| 720 | + | |
| 721 | + | |
| 722 | + | |
| 723 | + | |
| 724 | + | |
| 725 | + | |
| 726 | + | |
| 727 | + | |
| 728 | + | |
| 729 | + | |
| 730 | + | |
| 731 | + | |
| 732 | + | |
| 733 | + | |
| 734 | + | |
| 735 | + | |
| 736 | + | |
| 737 | + | |
| 738 | + | |
| 739 | + | |
| 740 | + | |
| 741 | + | |
| 742 | + | |
| 743 | + | |
| 744 | + | |
| 745 | + | |
| 746 | + | |
| 747 | + | |
| 748 | + | |
| 749 | + | |
| 750 | + | |
| 751 | + | |
| 752 | + | |
| 753 | + | |
| 754 | + | |
| 755 | + | |
| 756 | + | |
| 757 | + | |
| 758 | + | |
| 759 | + | |
649 | 760 | | |
650 | 761 | | |
651 | 762 | | |
| |||
Lines changed: 48 additions & 29 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
37 | 37 | | |
38 | 38 | | |
39 | 39 | | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
40 | 44 | | |
41 | 45 | | |
42 | 46 | | |
| |||
170 | 174 | | |
171 | 175 | | |
172 | 176 | | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
173 | 197 | | |
174 | 198 | | |
175 | 199 | | |
| |||
182 | 206 | | |
183 | 207 | | |
184 | 208 | | |
185 | | - | |
186 | | - | |
187 | | - | |
188 | | - | |
189 | | - | |
190 | | - | |
191 | | - | |
192 | | - | |
193 | | - | |
| 209 | + | |
194 | 210 | | |
195 | 211 | | |
196 | 212 | | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
197 | 225 | | |
198 | 226 | | |
199 | 227 | | |
| |||
220 | 248 | | |
221 | 249 | | |
222 | 250 | | |
223 | | - | |
224 | | - | |
225 | | - | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
226 | 256 | | |
227 | 257 | | |
228 | 258 | | |
| |||
475 | 505 | | |
476 | 506 | | |
477 | 507 | | |
| 508 | + | |
| 509 | + | |
478 | 510 | | |
479 | 511 | | |
480 | 512 | | |
481 | 513 | | |
482 | | - | |
483 | | - | |
484 | | - | |
485 | | - | |
486 | | - | |
487 | | - | |
488 | | - | |
489 | | - | |
490 | | - | |
| 514 | + | |
| 515 | + | |
491 | 516 | | |
492 | 517 | | |
493 | 518 | | |
| |||
541 | 566 | | |
542 | 567 | | |
543 | 568 | | |
544 | | - | |
545 | | - | |
546 | | - | |
547 | | - | |
548 | | - | |
549 | | - | |
550 | | - | |
551 | | - | |
| 569 | + | |
| 570 | + | |
552 | 571 | | |
553 | 572 | | |
554 | 573 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
7 | | - | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
8 | 11 | | |
9 | 12 | | |
10 | 13 | | |
| |||
18 | 21 | | |
19 | 22 | | |
20 | 23 | | |
21 | | - | |
22 | | - | |
23 | | - | |
24 | | - | |
25 | | - | |
26 | | - | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
27 | 34 | | |
28 | 35 | | |
29 | 36 | | |
30 | 37 | | |
31 | | - | |
| 38 | + | |
32 | 39 | | |
33 | 40 | | |
34 | 41 | | |
| |||
Lines changed: 21 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
688 | 688 | | |
689 | 689 | | |
690 | 690 | | |
| 691 | + | |
| 692 | + | |
| 693 | + | |
| 694 | + | |
| 695 | + | |
| 696 | + | |
| 697 | + | |
| 698 | + | |
| 699 | + | |
| 700 | + | |
| 701 | + | |
| 702 | + | |
| 703 | + | |
| 704 | + | |
| 705 | + | |
| 706 | + | |
| 707 | + | |
| 708 | + | |
| 709 | + | |
| 710 | + | |
| 711 | + | |
691 | 712 | | |
692 | 713 | | |
693 | 714 | | |
| |||
Lines changed: 9 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
247 | 247 | | |
248 | 248 | | |
249 | 249 | | |
250 | | - | |
| 250 | + | |
251 | 251 | | |
252 | 252 | | |
253 | 253 | | |
254 | 254 | | |
| 255 | + | |
255 | 256 | | |
256 | 257 | | |
257 | 258 | | |
| 259 | + | |
258 | 260 | | |
259 | 261 | | |
260 | | - | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
261 | 268 | | |
262 | 269 | | |
263 | 270 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
13 | 13 | | |
14 | 14 | | |
15 | 15 | | |
16 | | - | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
17 | 20 | | |
18 | 21 | | |
19 | 22 | | |
| |||
71 | 74 | | |
72 | 75 | | |
73 | 76 | | |
| 77 | + | |
74 | 78 | | |
75 | 79 | | |
76 | 80 | | |
| |||
Lines changed: 5 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
35 | 35 | | |
36 | 36 | | |
37 | 37 | | |
38 | | - | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
39 | 43 | | |
40 | 44 | | |
41 | 45 | | |
| |||
0 commit comments