Skip to content

Commit deb715d

Browse files
authored
fix(ramps): cp-7.59.0 buildquote screen flickering (#22326)
<!-- 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** There was a flickering issue when changing the payment method on the buy screen or the region on the sell screen. To fix the payment method issue, we just needed to remove it from the handleRegionChange dependency array. To fix the region issue, we needed to store a reference to the previously selected region and use that to check whether an update was necessary. <!-- 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? --> ## **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: null ## **Related issues** Fixes: #22313 ## **Manual testing steps** ```gherkin Feature: Buy flow - Change payment method Scenario: User changes the payment method during the Buy flow without UI flickering Given the user is on the asset details screen And a default payment method is selected When the user taps the "Buy" button And the bottom sheet appears And the user taps "Buy" again in the bottom sheet And the user taps "Payment Method" And the user selects a different payment method Then the selected payment method should update And the UI should transition smoothly with no flickering Feature: Sell flow - Change region Scenario: User changes the region during the Sell flow without UI flickering Given the user is on the asset details screen And a default region is selected When the user taps the "Buy" button And the bottom sheet appears And the user taps "Sell" in the bottom sheet And the user taps "Region" And the user selects a different region Then the selected region should update And the UI should transition smoothly with no flickering ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> payment method change issue: https://github.com/user-attachments/assets/53af19a7-72d3-41c3-968d-703949572049 region change issue: https://github.com/user-attachments/assets/cf85e687-a9ea-4606-a3e9-efbced95dc42 ### **After** <!-- [screenshots/recordings] --> payment method change fix: https://github.com/user-attachments/assets/2635c9fd-05dc-4a1f-83e2-c35723799290 region change fix: https://github.com/user-attachments/assets/4b103f2e-b6fc-4517-af21-6888c0b6995f ## **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] > Moves fiat-currency-on-region-change logic from BuildQuote to useFiatCurrencies with previous-region checks, and adds tests to validate behavior. > > - **Aggregator logic**: > - **`useFiatCurrencies`**: Adds `usePrevious(selectedRegion)` and effect to update `selectedFiatCurrencyId` when region changes only if using the default currency; queries new region default and updates selection. > - Maintains existing behaviors for selecting default currency and validating availability. > - **UI**: > - **`BuildQuote.tsx`**: Removes region-change fiat update effect and `setSelectedFiatCurrencyId` usage; relies on `useFiatCurrencies` for currency sync. > - **Tests**: > - **`useFiatCurrencies.test.ts`**: Adds tests for updating currency on region change when using default currency, and not updating when a custom currency is selected; includes `act` usage. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit e902222. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
1 parent 9ba9c85 commit deb715d

File tree

3 files changed

+134
-27
lines changed

3 files changed

+134
-27
lines changed

app/components/UI/Ramp/Aggregator/Views/BuildQuote/BuildQuote.tsx

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,6 @@ const BuildQuote = () => {
139139
selectedRegion,
140140
selectedAsset,
141141
selectedFiatCurrencyId,
142-
setSelectedFiatCurrencyId,
143142
selectedAddress,
144143
selectedNetworkName,
145144
sdkError,
@@ -183,7 +182,6 @@ const BuildQuote = () => {
183182
}, [paymentMethods, themeAppearance]);
184183

185184
const {
186-
defaultFiatCurrency,
187185
queryDefaultFiatCurrency,
188186
fiatCurrencies,
189187
queryGetFiatCurrencies,
@@ -245,31 +243,6 @@ const BuildQuote = () => {
245243
}, [shouldShowUnsupportedModal, navigation, regions, selectedRegion]),
246244
);
247245

248-
useEffect(() => {
249-
const handleRegionChange = async () => {
250-
if (
251-
selectedRegion &&
252-
selectedFiatCurrencyId === defaultFiatCurrency?.id
253-
) {
254-
const newRegionCurrency = await queryDefaultFiatCurrency(
255-
selectedRegion.id,
256-
);
257-
if (newRegionCurrency?.id) {
258-
setSelectedFiatCurrencyId(newRegionCurrency.id);
259-
}
260-
}
261-
};
262-
263-
handleRegionChange();
264-
}, [
265-
selectedRegion,
266-
selectedFiatCurrencyId,
267-
defaultFiatCurrency?.id,
268-
queryDefaultFiatCurrency,
269-
selectedPaymentMethodId,
270-
setSelectedFiatCurrencyId,
271-
]);
272-
273246
const gasLimitEstimation = useERC20GasLimitEstimation({
274247
tokenAddress: selectedAsset?.address,
275248
fromAddress: selectedAddress,

app/components/UI/Ramp/Aggregator/hooks/useFiatCurrencies.test.ts

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { act } from '@testing-library/react-native';
12
import { RampSDK } from '../sdk';
23
import useFiatCurrencies from './useFiatCurrencies';
34
import useSDKMethod from './useSDKMethod';
@@ -325,4 +326,107 @@ describe('useFiatCurrencies', () => {
325326
mockUseRampSDKValues.setSelectedFiatCurrencyId,
326327
).not.toHaveBeenCalled();
327328
});
329+
330+
it('updates currency when region changes and using default currency', async () => {
331+
const mockQueryDefaultFiatCurrency = jest.fn();
332+
const mockSetSelectedFiatCurrencyId = jest.fn();
333+
334+
mockUseRampSDKValues.selectedRegion = { id: 'region-1' };
335+
mockUseRampSDKValues.selectedFiatCurrencyId = 'default-fiat-currency-id';
336+
mockUseRampSDKValues.setSelectedFiatCurrencyId =
337+
mockSetSelectedFiatCurrencyId;
338+
339+
mockQueryDefaultFiatCurrency.mockResolvedValue({
340+
id: 'new-region-currency',
341+
});
342+
343+
(useSDKMethod as jest.Mock)
344+
.mockReturnValueOnce([
345+
{
346+
data: { id: 'default-fiat-currency-id' },
347+
error: null,
348+
isFetching: false,
349+
},
350+
mockQueryDefaultFiatCurrency,
351+
])
352+
.mockReturnValueOnce([
353+
{
354+
data: [{ id: 'default-fiat-currency-id' }],
355+
error: null,
356+
isFetching: false,
357+
},
358+
jest.fn(),
359+
])
360+
.mockReturnValueOnce([
361+
{
362+
data: { id: 'default-fiat-currency-id' },
363+
error: null,
364+
isFetching: false,
365+
},
366+
mockQueryDefaultFiatCurrency,
367+
])
368+
.mockReturnValueOnce([
369+
{
370+
data: [{ id: 'default-fiat-currency-id' }],
371+
error: null,
372+
isFetching: false,
373+
},
374+
jest.fn(),
375+
]);
376+
377+
const { rerender } = renderHookWithProvider(() => useFiatCurrencies());
378+
379+
mockUseRampSDKValues.selectedRegion = { id: 'region-2' };
380+
381+
await act(async () => {
382+
rerender(() => useFiatCurrencies());
383+
await new Promise((resolve) => setTimeout(resolve, 50));
384+
});
385+
386+
expect(mockQueryDefaultFiatCurrency).toHaveBeenCalledWith('region-2');
387+
expect(mockSetSelectedFiatCurrencyId).toHaveBeenCalledWith(
388+
'new-region-currency',
389+
);
390+
});
391+
392+
it('does not update currency when region changes but not using default currency', async () => {
393+
const mockQueryDefaultFiatCurrency = jest.fn();
394+
const mockSetSelectedFiatCurrencyId = jest.fn();
395+
396+
mockUseRampSDKValues.selectedRegion = { id: 'region-1' };
397+
mockUseRampSDKValues.selectedFiatCurrencyId = 'custom-currency-id';
398+
mockUseRampSDKValues.setSelectedFiatCurrencyId =
399+
mockSetSelectedFiatCurrencyId;
400+
401+
(useSDKMethod as jest.Mock)
402+
.mockReturnValue([
403+
{
404+
data: { id: 'default-fiat-currency-id' },
405+
error: null,
406+
isFetching: false,
407+
},
408+
mockQueryDefaultFiatCurrency,
409+
])
410+
.mockReturnValue([
411+
{
412+
data: [
413+
{ id: 'custom-currency-id' },
414+
{ id: 'default-fiat-currency-id' },
415+
],
416+
error: null,
417+
isFetching: false,
418+
},
419+
jest.fn(),
420+
]);
421+
422+
const { rerender } = renderHookWithProvider(() => useFiatCurrencies());
423+
424+
mockUseRampSDKValues.selectedRegion = { id: 'region-2' };
425+
426+
rerender(() => useFiatCurrencies());
427+
428+
await new Promise((resolve) => setTimeout(resolve, 50));
429+
430+
expect(mockSetSelectedFiatCurrencyId).not.toHaveBeenCalled();
431+
});
328432
});

app/components/UI/Ramp/Aggregator/hooks/useFiatCurrencies.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { useEffect, useMemo } from 'react';
22
import { useRampSDK } from '../sdk';
33
import useSDKMethod from './useSDKMethod';
4+
import usePrevious from '../../../../hooks/usePrevious';
45

56
export default function useFiatCurrencies() {
67
const {
@@ -75,6 +76,35 @@ export default function useFiatCurrencies() {
7576
setSelectedFiatCurrencyId,
7677
]);
7778

79+
const previousRegion = usePrevious(selectedRegion);
80+
81+
/**
82+
* Update fiat currency when region changes and using default currency.
83+
*/
84+
useEffect(() => {
85+
const handleRegionChange = async () => {
86+
if (selectedRegion && previousRegion?.id !== selectedRegion.id) {
87+
if (selectedFiatCurrencyId === defaultFiatCurrency?.id) {
88+
const newRegionCurrency = await queryDefaultFiatCurrency(
89+
selectedRegion.id,
90+
);
91+
if (newRegionCurrency?.id) {
92+
setSelectedFiatCurrencyId(newRegionCurrency.id);
93+
}
94+
}
95+
}
96+
};
97+
98+
handleRegionChange();
99+
}, [
100+
selectedRegion,
101+
previousRegion,
102+
selectedFiatCurrencyId,
103+
defaultFiatCurrency?.id,
104+
queryDefaultFiatCurrency,
105+
setSelectedFiatCurrencyId,
106+
]);
107+
78108
/**
79109
* Get the fiat currency object by id
80110
*/

0 commit comments

Comments
 (0)