Commit acacfde
authored
fix(ramps): Remove dual-path fetching from RampsController, let client own data lifecycle (#8354)
## Explanation
Payment methods, providers, and tokens were being fetched redundantly
from two independent paths: the controller's `fireAndForget` calls
(inside `setSelectedToken`, `setSelectedProvider`, and `setUserRegion`)
and React Query on the mobile side. This caused 2–3 duplicate API calls
per user action, with a ~10s spinner on the `/payments` endpoint due to
cold DB connection pooling.
This PR removes all `fireAndForget` data-fetching side effects from the
controller. The mobile client (React Query + RampsBootstrap) is now the
single owner of when providers, tokens, and payment methods are fetched.
The controller only manages state updates and selections.
Changes:
1. **`#runInit` (geolocation fix)** — `forceRefresh` no longer overrides
a persisted `userRegion` with the geolocation endpoint. Geolocation is
only used to seed the initial region when `userRegion` is null.
2. **`setSelectedToken`** — Removed
`fireAndForget(getPaymentMethods(...))` and
`resetResource('paymentMethods')`. Token change no longer triggers
payment methods fetch or clears payment methods state. Payment methods
are provider-scoped, not token-scoped.
3. **`setSelectedProvider`** — Removed
`fireAndForget(getPaymentMethods(...))`,
`resetResource('paymentMethods')`, and `tokenSupportedByProvider` gate.
Now accepts a full `Provider` object (not just ID) to avoid dependency
on `state.providers.data` being populated. Silently ignores when
provider ID is not found instead of throwing.
4. **`setUserRegion`** — Removed `fireAndForget(getTokens(...))` and
`fireAndForget(getProviders(...))`. The mobile client handles all data
fetching via React Query (providers, payment methods) and direct
controller calls (tokens) from RampsBootstrap.
5. **`setSelectedPaymentMethod`** — Now accepts a full `PaymentMethod`
object (not just ID) to avoid dependency on `state.paymentMethods.data`
being populated. Silently sets `null` when payment method ID is not
found instead of throwing.
6. **`getPaymentMethods` response handler** — Always selects the first
(highest-scored) payment method when new data arrives, preventing
dead-end states where a payment method with no quotes stays selected
after provider switch.
7. **`#fireAndForget`** — Removed (no remaining callers).
8. **`executeRequest` generation counter** — Added
`#pendingResourceGeneration` map to prevent stale in-flight requests
from corrupting `isLoading` state. When `setUserRegion` resets dependent
resource counts, the generation is bumped. Orphaned finally blocks from
the previous generation skip their decrement instead of prematurely
clearing `isLoading`.
## Link to metamask-mobile
Depends on mobile PR:
[MetaMask/metamask-mobile#28224](MetaMask/metamask-mobile#28224)
## References
[TRAM-3398](https://consensyssoftware.atlassian.net/browse/TRAM-3398)
## Changelog
CHANGELOG entry: See `packages/ramps-controller/CHANGELOG.md` Unreleased
section.
## Checklist
- [x] I've updated the test suite for new or updated code as appropriate
- [x] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [x] I've communicated my changes to consumers by [updating changelogs
for packages I've
changed](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md)
- [ ] I've introduced [breaking
changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md)
in this PR and have prepared draft pull requests for clients and
consumer packages to resolve them
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Medium Risk**
> Behavior changes in `RampsController` selection/region flows (no
longer auto-fetching or clearing dependent data) could affect consumers
that relied on controller-side side effects. Adds new stale-request
invalidation for `executeRequest`, which impacts loading/error state
handling across resources.
>
> **Overview**
> **Shifts ramps data lifecycle ownership to the client** by removing
controller-side `fireAndForget` fetching from `setUserRegion`,
`setSelectedToken`, and `setSelectedProvider`, and by no longer clearing
`paymentMethods` on token/provider changes.
>
> `setSelectedProvider` and `setSelectedPaymentMethod` now accept either
an ID or a full object and **stop throwing when backing resource data
isn’t loaded/not found** (silently leaving selection `null`). `init` is
fixed to **never override a persisted `userRegion` with geolocation**,
even on `forceRefresh`.
>
> Request tracking is hardened by adding a per-resource generation
counter so stale in-flight requests can’t incorrectly decrement
ref-counted `isLoading` after dependent-resource resets; tests are
updated/added to cover these races and the new selection semantics.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
7073fe5. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->1 parent 04bc584 commit acacfde
4 files changed
Lines changed: 418 additions & 257 deletions
File tree
- packages/ramps-controller
- src
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
11 | 11 | | |
12 | 12 | | |
13 | 13 | | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
14 | 20 | | |
15 | 21 | | |
16 | 22 | | |
| |||
Lines changed: 13 additions & 9 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
70 | 70 | | |
71 | 71 | | |
72 | 72 | | |
73 | | - | |
74 | | - | |
75 | | - | |
| 73 | + | |
76 | 74 | | |
77 | | - | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
78 | 80 | | |
79 | 81 | | |
80 | 82 | | |
81 | 83 | | |
82 | | - | |
83 | 84 | | |
84 | 85 | | |
85 | 86 | | |
| |||
177 | 178 | | |
178 | 179 | | |
179 | 180 | | |
180 | | - | |
181 | | - | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
182 | 187 | | |
183 | | - | |
184 | | - | |
| 188 | + | |
185 | 189 | | |
186 | 190 | | |
187 | 191 | | |
| |||
0 commit comments