Skip to content

Commit ae9937b

Browse files
temp+chore: cp-7.51.0 faster address checksum (#16926) (#17174)
## **Description** This [PR](#16926) is originally from @Nodonisko from Margelo This PR uses new faster memoized functions for working with address checksum. There is already significant boost in AccountList performance and it should be even better when MetaMask/core#6054 is released and also when we fix Blockies Avatars. ## **Related issues** Fixes: #15560 ## **Manual testing steps** 1. Open Account List 2. It should feel faster than before ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** You can set that before then was lot of interrupted work before Account List modal is even displayed. It takes around ~7s from click to modal to be actually visible. <img width="1324" alt="Screenshot 2025-07-03 at 21 36 06" src="https://github.com/user-attachments/assets/7c624f31-db84-4ade-9df6-a116bff9a68f" /> ### **After** Here it takes only around ~3s to mount. (still slow but much better than before) <img width="1325" alt="Screenshot 2025-07-03 at 21 38 16" src="https://github.com/user-attachments/assets/96a5a4f1-59b7-4cfa-b58c-ac84eb238654" /> ## **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** - [x] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [x] 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. <!-- 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? --> ## **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: ## **Related issues** Fixes: ## **Manual testing steps** 1. Go to this page... 2. 3. ## **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** - [ ] 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). - [ ] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] 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. Co-authored-by: Daniel Suchý <suchydan@gmail.com>
1 parent 09d0237 commit ae9937b

File tree

524 files changed

+7459
-32403
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

524 files changed

+7459
-32403
lines changed

.depcheckrc.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ ignores:
5353
- 'improved-yarn-audit'
5454
- 'jetifier'
5555
- 'metro-react-native-babel-preset'
56+
- 'octonode'
5657
- 'prettier-plugin-gherkin'
5758
- 'react-native-svg-asset-plugin'
5859
- 'regenerator-runtime'

.e2e.env.example

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,3 @@ export USE_LOCAL_DAPP=true
1616
export MULTICHAIN_DAPP_URL="https://metamask.github.io/test-dapp-multichain/latest/"
1717
# Option 2: Use a custom remote URL
1818
# export MULTICHAIN_DAPP_URL="https://your-multichain-dapp.example.com/"
19-
20-
# E2E prebuild paths
21-
export PREBUILT_IOS_APP_PATH='build/MetaMask.app'
22-
export PREBUILT_ANDROID_APK_PATH='build/MetaMask.apk'
23-
export PREBUILT_ANDROID_TEST_APK_PATH='build/MetaMask-Test.apk'

.github/CODEOWNERS

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ app/components/UI/Card/ @MetaMask/card
5353

5454
# Confirmation Team
5555
app/components/Views/confirmations @MetaMask/confirmations
56-
app/components/Views/confirmations/external/staking @MetaMask/confirmations @MetaMask/metamask-earn
5756
app/core/Engine/controllers/approval-controller @MetaMask/confirmations
5857
app/core/Engine/controllers/gas-fee-controller @MetaMask/confirmations
5958
app/core/Engine/controllers/signature-controller @MetaMask/confirmations

.github/workflows/stable-branch-sync.yml

Lines changed: 0 additions & 47 deletions
This file was deleted.

.gitignore

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -144,9 +144,3 @@ github-tools/
144144

145145
# API Monitor logs
146146
api-monitor-logs/
147-
148-
# Claude AI development files
149-
CLAUDE.md
150-
/CLAUDE.md
151-
temp/
152-
/temp/

.storybook/storybook.requires.js

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

CHANGELOG.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10-
- fix: Security vulnerability in RPC domain validation that could allow malicious domains to be misclassified as legitimate providers ([#17234](https://github.com/MetaMask/metamask-mobile/pull/17234))
11-
1210
## [7.50.1]
1311

1412
### Fixed

android/app/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,8 +187,8 @@ android {
187187
applicationId "io.metamask"
188188
minSdkVersion rootProject.ext.minSdkVersion
189189
targetSdkVersion rootProject.ext.targetSdkVersion
190-
versionName "7.50.1"
191-
versionCode 2103
190+
versionName "7.52.0"
191+
versionCode 2149
192192
testBuildType System.getProperty('testBuildType', 'debug')
193193
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
194194
manifestPlaceholders.MM_BRANCH_KEY_TEST = "$System.env.MM_BRANCH_KEY_TEST"

app/actions/multiSrp/index.test.ts

Lines changed: 5 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import {
88
} from './';
99
import { wordlist } from '@metamask/scure-bip39/dist/wordlists/english';
1010
import { createMockInternalAccount } from '../../util/test/accountsControllerTestUtils';
11-
import { TraceName, TraceOperation } from '../../util/trace';
1211
import ReduxService from '../../core/redux/ReduxService';
1312
import { RootState } from '../../reducers';
1413

@@ -29,12 +28,6 @@ const mockControllerMessenger = jest.fn();
2928
const mockAddDiscoveredAccounts = jest.fn();
3029
const mockGetAccountByAddress = jest.fn().mockReturnValue(mockExpectedAccount);
3130

32-
// Mock for seedless onboarding
33-
const mockSelectSeedlessOnboardingLoginFlow = jest.fn();
34-
const mockAddNewSeedPhraseBackup = jest.fn();
35-
const mockTrace = jest.fn();
36-
const mockEndTrace = jest.fn();
37-
3831
const hdKeyring = {
3932
getAccounts: () => {
4033
mockGetAccounts();
@@ -50,17 +43,6 @@ const mockSnapClient = {
5043
addDiscoveredAccounts: mockAddDiscoveredAccounts,
5144
};
5245

53-
jest.mock('../../selectors/seedlessOnboardingController', () => ({
54-
selectSeedlessOnboardingLoginFlow: (state: unknown) =>
55-
mockSelectSeedlessOnboardingLoginFlow(state),
56-
}));
57-
58-
jest.mock('../../util/trace', () => ({
59-
...jest.requireActual('../../util/trace'),
60-
trace: (options: unknown) => mockTrace(options),
61-
endTrace: (options: unknown) => mockEndTrace(options),
62-
}));
63-
6446
const createMockState = (hasVault: boolean) => ({
6547
engine: {
6648
backgroundState: {
@@ -99,8 +81,7 @@ jest.mock('../../core/Engine', () => ({
9981
getAccountByAddress: () => mockGetAccountByAddress(),
10082
},
10183
SeedlessOnboardingController: {
102-
addNewSeedPhraseBackup: (seed: Uint8Array, keyringId: string) =>
103-
mockAddNewSeedPhraseBackup(seed, keyringId),
84+
addNewSeedPhraseBackup: jest.fn().mockResolvedValue(undefined),
10485
},
10586
},
10687
setSelectedAddress: (address: string) => mockSetSelectedAddress(address),
@@ -122,11 +103,7 @@ describe('MultiSRP Actions', () => {
122103
describe('importNewSecretRecoveryPhrase', () => {
123104
it('imports new SRP', async () => {
124105
mockGetKeyringsByType.mockResolvedValue([]);
125-
mockAddNewKeyring.mockResolvedValue({
126-
getAccounts: () => [testAddress],
127-
id: 'keyring-id-123',
128-
});
129-
mockSelectSeedlessOnboardingLoginFlow.mockReturnValue(false);
106+
mockAddNewKeyring.mockResolvedValue({ getAccounts: () => [testAddress] });
130107

131108
await importNewSecretRecoveryPhrase(testMnemonic);
132109

@@ -154,74 +131,7 @@ describe('MultiSRP Actions', () => {
154131
expect(mockAddNewKeyring).not.toHaveBeenCalled();
155132
});
156133

157-
describe('seedless onboarding login flow', () => {
158-
beforeEach(() => {
159-
mockGetKeyringsByType.mockResolvedValue([]);
160-
mockAddNewKeyring.mockResolvedValue({
161-
getAccounts: () => [testAddress],
162-
id: 'keyring-id-123',
163-
});
164-
mockSelectSeedlessOnboardingLoginFlow.mockReturnValue(true);
165-
});
166-
167-
it('successfully adds seed phrase backup when seedless onboarding is enabled', async () => {
168-
mockAddNewSeedPhraseBackup.mockResolvedValue(undefined);
169-
170-
const result = await importNewSecretRecoveryPhrase(testMnemonic);
171-
172-
expect(mockSelectSeedlessOnboardingLoginFlow).toHaveBeenCalled();
173-
expect(mockTrace).toHaveBeenCalledWith({
174-
name: TraceName.OnboardingAddSrp,
175-
op: TraceOperation.OnboardingSecurityOp,
176-
});
177-
expect(mockAddNewSeedPhraseBackup).toHaveBeenCalledWith(
178-
expect.any(Uint8Array),
179-
'keyring-id-123',
180-
);
181-
expect(mockEndTrace).toHaveBeenCalledWith({
182-
name: TraceName.OnboardingAddSrp,
183-
data: { success: true },
184-
});
185-
expect(mockSetSelectedAddress).toHaveBeenCalledWith(testAddress);
186-
expect(result.address).toBe(testAddress);
187-
expect(mockAddDiscoveredAccounts).toHaveBeenCalled();
188-
});
189-
190-
it('handles error when seed phrase backup fails and traces error', async () => {
191-
mockAddNewSeedPhraseBackup.mockRejectedValue(
192-
new Error('Backup failed'),
193-
);
194-
195-
await expect(
196-
async () => await importNewSecretRecoveryPhrase(testMnemonic),
197-
).rejects.toThrow('Backup failed');
198-
199-
expect(mockSelectSeedlessOnboardingLoginFlow).toHaveBeenCalled();
200-
expect(mockTrace).toHaveBeenCalledWith({
201-
name: TraceName.OnboardingAddSrp,
202-
op: TraceOperation.OnboardingSecurityOp,
203-
});
204-
expect(mockAddNewSeedPhraseBackup).toHaveBeenCalledWith(
205-
expect.any(Uint8Array),
206-
'keyring-id-123',
207-
);
208-
expect(mockTrace).toHaveBeenCalledWith({
209-
name: TraceName.OnboardingAddSrpError,
210-
op: TraceOperation.OnboardingError,
211-
tags: { errorMessage: 'Backup failed' },
212-
});
213-
expect(mockEndTrace).toHaveBeenCalledWith({
214-
name: TraceName.OnboardingAddSrpError,
215-
});
216-
expect(mockEndTrace).toHaveBeenCalledWith({
217-
name: TraceName.OnboardingAddSrp,
218-
data: { success: false },
219-
});
220-
});
221-
});
222-
223134
it('calls addNewSeedPhraseBackup when seedless onboarding login flow is active', async () => {
224-
mockAddNewSeedPhraseBackup.mockResolvedValue(undefined);
225135
mockGetKeyringsByType.mockResolvedValue([]);
226136
mockAddNewKeyring.mockResolvedValue({
227137
id: 'test-keyring-id',
@@ -234,10 +144,9 @@ describe('MultiSRP Actions', () => {
234144

235145
await importNewSecretRecoveryPhrase(testMnemonic);
236146

237-
expect(mockAddNewSeedPhraseBackup).toHaveBeenCalledWith(
238-
expect.any(Uint8Array),
239-
'test-keyring-id',
240-
);
147+
expect(
148+
Engine.context.SeedlessOnboardingController.addNewSeedPhraseBackup,
149+
).toHaveBeenCalledWith(expect.any(Uint8Array), 'test-keyring-id');
241150
});
242151
});
243152

app/actions/multiSrp/index.ts

Lines changed: 6 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,22 @@ import ExtendedKeyringTypes from '../../constants/keyringTypes';
44
import Engine from '../../core/Engine';
55
import { KeyringSelector } from '@metamask/keyring-controller';
66
import { InternalAccount } from '@metamask/keyring-internal-api';
7-
///: BEGIN:ONLY_INCLUDE_IF(keyring-snaps)
7+
///: BEGIN:ONLY_INCLUDE_IF(solana)
88
import {
99
MultichainWalletSnapFactory,
1010
WalletClientType,
1111
} from '../../core/SnapKeyring/MultichainWalletSnapClient';
1212
///: END:ONLY_INCLUDE_IF
13-
import {
14-
///: BEGIN:ONLY_INCLUDE_IF(solana)
15-
SolScope,
16-
///: END:ONLY_INCLUDE_IF
17-
///: BEGIN:ONLY_INCLUDE_IF(bitcoin)
18-
BtcScope,
19-
///: END:ONLY_INCLUDE_IF
20-
} from '@metamask/keyring-api';
2113
import {
2214
endPerformanceTrace,
2315
startPerformanceTrace,
2416
} from '../../core/redux/slices/performance';
2517
import { PerformanceEventNames } from '../../core/redux/slices/performance/constants';
2618
import { store } from '../../store';
19+
import { endTrace, trace, TraceName, TraceOperation } from '../../util/trace';
2720
import { getTraceTags } from '../../util/sentry/tags';
2821

2922
import ReduxService from '../../core/redux';
30-
import { TraceName, TraceOperation, trace, endTrace } from '../../util/trace';
3123
import { selectSeedlessOnboardingLoginFlow } from '../../selectors/seedlessOnboardingController';
3224

3325
export async function importNewSecretRecoveryPhrase(mnemonic: string) {
@@ -85,61 +77,26 @@ export async function importNewSecretRecoveryPhrase(mnemonic: string) {
8577
// on Error, wallet should notify user that the newly added seed phrase is not synced properly
8678
// user can try manual sync again (phase 2)
8779
const seed = new Uint8Array(inputCodePoints.buffer);
88-
let addSeedPhraseSuccess = false;
8980
try {
90-
trace({
91-
name: TraceName.OnboardingAddSrp,
92-
op: TraceOperation.OnboardingSecurityOp,
93-
});
9481
await SeedlessOnboardingController.addNewSeedPhraseBackup(
9582
seed,
9683
newKeyring.id,
9784
);
98-
addSeedPhraseSuccess = true;
9985
} catch (error) {
100-
const errorMessage =
101-
error instanceof Error ? error.message : 'Unknown error';
10286
// Log the error but don't let it crash the import process
103-
console.error('Failed to backup seed phrase:', errorMessage);
104-
105-
trace({
106-
name: TraceName.OnboardingAddSrpError,
107-
op: TraceOperation.OnboardingError,
108-
tags: { errorMessage },
109-
});
110-
endTrace({
111-
name: TraceName.OnboardingAddSrpError,
112-
});
113-
114-
throw error;
115-
} finally {
116-
endTrace({
117-
name: TraceName.OnboardingAddSrp,
118-
data: { success: addSeedPhraseSuccess },
119-
});
87+
console.error('Failed to backup seed phrase:', error);
12088
}
12189
}
12290

12391
let discoveredAccountsCount = 0;
12492

125-
///: BEGIN:ONLY_INCLUDE_IF(bitcoin)
126-
const bitcoinMultichainClient = MultichainWalletSnapFactory.createClient(
127-
WalletClientType.Bitcoin,
128-
);
129-
discoveredAccountsCount +=
130-
await bitcoinMultichainClient.addDiscoveredAccounts(
131-
newKeyring.id,
132-
BtcScope.Mainnet,
133-
);
134-
///: END:ONLY_INCLUDE_IF
135-
13693
///: BEGIN:ONLY_INCLUDE_IF(solana)
137-
const solanaMultichainClient = MultichainWalletSnapFactory.createClient(
94+
const multichainClient = MultichainWalletSnapFactory.createClient(
13895
WalletClientType.Solana,
13996
);
140-
discoveredAccountsCount += await solanaMultichainClient.addDiscoveredAccounts(
97+
98+
discoveredAccountsCount = await multichainClient.addDiscoveredAccounts(
14199
newKeyring.id,
142-
SolScope.Mainnet,
143100
);
144101
///: END:ONLY_INCLUDE_IF
145102

0 commit comments

Comments
 (0)