Skip to content

Commit b22bfcc

Browse files
authored
fix: cp-7.47.0 Add safe checksum method in SendTo page (#15308)
<!-- 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** <!-- 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? --> This PR aims to fix an issue when user puts an unexpected value into `to` field in send flow. It appears from that [the issue](https://metamask.sentry.io/issues/6582066742/?project=2299799) is thrown by `toChecksumAddress` because it doesn't expect any incomplete address. However in send flow UX we let user to type in address themselves. To test this you can go `SendTo` page and put `K` for example - and see the crash. (Screenshot below is fixed version) **Labels** Adding `skip-sonar-cloud` as the raised issue was intentional. ![Screenshot 2025-05-14 at 06 44 09](https://github.com/user-attachments/assets/fda651bc-4925-40d8-95ca-2cabd7cbed66) ## **Related issues** Fixes: #15094 ## **Manual testing steps** 1. Go to send flow 2. Input an unexpected address 3. Confirm warning shown - you shouldn't be proceed next step ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **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.
1 parent acfbd30 commit b22bfcc

File tree

4 files changed

+35
-6
lines changed

4 files changed

+35
-6
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
4646
- fix(bridge): fix transaction history for EVM and Solana bridge transactions ([#14759](https://github.com/MetaMask/metamask-mobile/pull/14759))
4747
- fix(bridge): change networks properly when user switches between source and destination tokens ([#14812](https://github.com/MetaMask/metamask-mobile/pull/14812))
4848
- fix(bridge): fix(bridge): update quote details card toggle to handle same chain swaps and improve slippage button layout ([#15153](https://github.com/MetaMask/metamask-mobile/pull/15153))
49+
- fix(confirmations): fix the send crash when user puts unexpected address into recipient input([#15308](https://github.com/MetaMask/metamask-mobile/pull/15308))
4950

5051
## [7.45.2]
5152

app/components/Views/confirmations/legacy/SendFlow/SendTo/__snapshots__/index.test.tsx.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Jest Snapshot v1, https://goo.gl/fbAQLP
22

3-
exports[`SendTo Component should render 1`] = `
3+
exports[`SendTo Component render matches snapshot 1`] = `
44
<RNCSafeAreaView
55
edges={
66
[

app/components/Views/confirmations/legacy/SendFlow/SendTo/index.js

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ class SendFlow extends PureComponent {
224224
const { toAccount } = this.state;
225225
const { addressBook, globalChainId, internalAccounts } = this.props;
226226
const networkAddressBook = addressBook[globalChainId] || {};
227-
const checksummedAddress = toChecksumAddress(toAccount);
227+
const checksummedAddress = this.safeChecksumAddress(toAccount);
228228
return !!(
229229
networkAddressBook[checksummedAddress] ||
230230
internalAccounts.find((account) =>
@@ -381,7 +381,7 @@ class SendFlow extends PureComponent {
381381

382382
const networkAddressBook = addressBook[globalChainId] || {};
383383

384-
const checksummedAddress = toChecksumAddress(toAccount);
384+
const checksummedAddress = this.safeChecksumAddress(toAccount);
385385
const matchingAccount = internalAccounts.find((account) =>
386386
toLowerCaseEquals(account.address, checksummedAddress),
387387
);
@@ -481,6 +481,14 @@ class SendFlow extends PureComponent {
481481
this.setState({ showAmbiguousAcountWarning: false });
482482
};
483483

484+
safeChecksumAddress = (address) => {
485+
try {
486+
return toChecksumAddress(address);
487+
} catch (error) {
488+
return address;
489+
}
490+
};
491+
484492
render = () => {
485493
const { ticker, addressBook, globalChainId } = this.props;
486494
const {
@@ -499,7 +507,7 @@ class SendFlow extends PureComponent {
499507
const colors = this.context.colors || mockTheme.colors;
500508
const styles = createStyles(colors);
501509

502-
const checksummedAddress = toAccount && toChecksumAddress(toAccount);
510+
const checksummedAddress = this.safeChecksumAddress(toAccount);
503511
const existingAddressName = this.getAddressNameFromBookOrInternalAccounts(
504512
toEnsAddressResolved || toAccount,
505513
);

app/components/Views/confirmations/legacy/SendFlow/SendTo/index.test.tsx

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import SendTo from './index';
88
import { ThemeContext, mockTheme } from '../../../../../../util/theme';
99
import initialRootState from '../../../../../../util/test/initial-root-state';
1010
import { validateAddressOrENS } from '../../../../../../util/address';
11+
import { SendViewSelectorsIDs } from '../../../../../../../e2e/selectors/SendFlow/SendView.selectors';
1112

1213
jest.mock('@react-navigation/native', () => {
1314
const actualNav = jest.requireActual('@react-navigation/native');
@@ -54,7 +55,7 @@ describe('SendTo Component', () => {
5455
);
5556
});
5657

57-
it('should render', () => {
58+
it('render matches snapshot', () => {
5859
const wrapper = render(
5960
<Provider store={store}>
6061
<ThemeContext.Provider value={mockTheme}>
@@ -65,7 +66,7 @@ describe('SendTo Component', () => {
6566
expect(wrapper).toMatchSnapshot();
6667
});
6768

68-
it('should navigate to Amount screen', () => {
69+
it('navigates to Amount screen', () => {
6970
const MOCK_TARGET_ADDRESS = '0x0000000000000000000000000000000000000000';
7071
const { navigate } = navigationPropMock;
7172
const routeProps = {
@@ -86,4 +87,23 @@ describe('SendTo Component', () => {
8687
fireEvent.press(screen.getByText('Next'));
8788
expect(navigate).toHaveBeenCalledWith('Amount');
8889
});
90+
91+
it('shows the warning message when the target address is invalid', () => {
92+
const { getByText, getByTestId } = render(
93+
<Provider store={store}>
94+
<ThemeContext.Provider value={mockTheme}>
95+
<SendTo navigation={navigationPropMock} route={routeMock} />
96+
</ThemeContext.Provider>
97+
</Provider>,
98+
);
99+
100+
const toInput = getByTestId(SendViewSelectorsIDs.ADDRESS_INPUT);
101+
fireEvent.changeText(toInput, 'invalid address');
102+
103+
const expectedWarningMessage = getByText(
104+
'No address has been set for this name.',
105+
);
106+
107+
expect(expectedWarningMessage).toBeOnTheScreen();
108+
});
89109
});

0 commit comments

Comments
 (0)