Skip to content

Commit b2067a5

Browse files
AxelGesjoaoloureirop
authored andcommitted
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 dc7c66d commit b2067a5

3 files changed

Lines changed: 134 additions & 27 deletions

File tree

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

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,6 @@ const BuildQuote = () => {
141141
selectedRegion,
142142
selectedAsset,
143143
selectedFiatCurrencyId,
144-
setSelectedFiatCurrencyId,
145144
selectedAddress,
146145
selectedNetworkName,
147146
sdkError,
@@ -185,7 +184,6 @@ const BuildQuote = () => {
185184
}, [paymentMethods, themeAppearance]);
186185

187186
const {
188-
defaultFiatCurrency,
189187
queryDefaultFiatCurrency,
190188
fiatCurrencies,
191189
queryGetFiatCurrencies,
@@ -247,31 +245,6 @@ const BuildQuote = () => {
247245
}, [shouldShowUnsupportedModal, navigation, regions, selectedRegion]),
248246
);
249247

250-
useEffect(() => {
251-
const handleRegionChange = async () => {
252-
if (
253-
selectedRegion &&
254-
selectedFiatCurrencyId === defaultFiatCurrency?.id
255-
) {
256-
const newRegionCurrency = await queryDefaultFiatCurrency(
257-
selectedRegion.id,
258-
);
259-
if (newRegionCurrency?.id) {
260-
setSelectedFiatCurrencyId(newRegionCurrency.id);
261-
}
262-
}
263-
};
264-
265-
handleRegionChange();
266-
}, [
267-
selectedRegion,
268-
selectedFiatCurrencyId,
269-
defaultFiatCurrency?.id,
270-
queryDefaultFiatCurrency,
271-
selectedPaymentMethodId,
272-
setSelectedFiatCurrencyId,
273-
]);
274-
275248
const gasLimitEstimation = useERC20GasLimitEstimation({
276249
tokenAddress: selectedAsset?.address,
277250
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)