Skip to content

Commit 7126936

Browse files
authored
Merge branch 'main' into account_selection
2 parents 816be55 + 0385ea0 commit 7126936

File tree

74 files changed

+3435
-14687
lines changed

Some content is hidden

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

74 files changed

+3435
-14687
lines changed

.depcheckrc.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ ignores:
1515
- 'react-compiler-runtime'
1616
# This is used on the patch for TokenRatesController of Assets controllers, for we to be able to use the last version of it
1717
- cockatiel
18+
# These are used in metro.config.js to setup Hardened JavaScript via @lavamoat/react-native-lockdown
19+
- '@react-native/js-polyfills'
20+
- 'reflect-metadata'
1821

1922
# Note: Everything below this line should be removed after investigation
2023
# TODO: Investigate each dependency to see whether it's used
@@ -105,4 +108,4 @@ ignores:
105108
- '@react-native/typescript-config'
106109
- 'react-native-pager-view'
107110
# this dependency can probably be removed, needs investigation
108-
- '@types/react-test-renderer'
111+
- '@types/react-test-renderer'

CHANGELOG.md

Lines changed: 59 additions & 103 deletions
Large diffs are not rendered by default.

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.47.1"
191-
versionCode 2004
190+
versionName "7.47.3"
191+
versionCode 2051
192192
testBuildType System.getProperty('testBuildType', 'debug')
193193
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
194194
manifestPlaceholders.MM_BRANCH_KEY_TEST = "$System.env.MM_BRANCH_KEY_TEST"

android/app/src/main/java/io/metamask/MainApplication.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ import expo.modules.ReactNativeHostWrapper
2525

2626
import cl.json.ShareApplication
2727
import io.branch.rnbranch.RNBranchModule
28-
import com.airbnb.android.react.lottie.LottiePackage
2928
import io.metamask.nativeModules.PreventScreenshotPackage
3029
import io.metamask.nativeModules.RCTMinimizerPackage
3130
import io.metamask.nativesdk.NativeSDKPackage
@@ -41,7 +40,6 @@ class MainApplication : Application(), ShareApplication, ReactApplication {
4140
override fun getPackages(): List<ReactPackage> {
4241
val packages = PackageList(this).packages.toMutableList()
4342
// Add all our custom packages
44-
packages.add(LottiePackage())
4543
packages.add(PreventScreenshotPackage())
4644
packages.add(RCTMinimizerPackage())
4745
packages.add(NativeSDKPackage())

android/settings.gradle

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,6 @@ dependencyResolutionManagement {
3939
include ':app'
4040
includeBuild(new File(["node", "--print", "require.resolve('@react-native/gradle-plugin/package.json', { paths: [require.resolve('react-native/package.json')] })"].execute(null, rootDir).text.trim()).getParentFile())
4141
includeBuild('../node_modules/@react-native') {}
42-
include ':lottie-react-native'
43-
project(':lottie-react-native').projectDir = new File(rootProject.projectDir, '../node_modules/lottie-react-native/src/android')
4442
include ':react-native-gesture-handler'
4543
project(':react-native-gesture-handler').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-gesture-handler/android')
4644

app/actions/user/index.ts

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import {
2323
type PersistedDataLoadedAction,
2424
type SetAppServicesReadyAction,
2525
UserActionType,
26-
type SetMetaMetricsUISeenAction,
2726
} from './types';
2827

2928
export * from './types';
@@ -177,14 +176,3 @@ export function setAppServicesReady(): SetAppServicesReadyAction {
177176
type: UserActionType.SET_APP_SERVICES_READY,
178177
};
179178
}
180-
181-
export function setMetaMetricsUISeen(
182-
isMetaMetricsUISeen: boolean,
183-
): SetMetaMetricsUISeenAction {
184-
return {
185-
type: UserActionType.SET_META_METRICS_UI_SEEN,
186-
payload: {
187-
isMetaMetricsUISeen,
188-
},
189-
};
190-
}

app/actions/user/types.ts

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -93,11 +93,6 @@ export type CheckedAuthAction = Action<UserActionType.CHECKED_AUTH> & {
9393
export type SetAppServicesReadyAction =
9494
Action<UserActionType.SET_APP_SERVICES_READY>;
9595

96-
export type SetMetaMetricsUISeenAction =
97-
Action<UserActionType.SET_META_METRICS_UI_SEEN> & {
98-
payload: { isMetaMetricsUISeen: boolean };
99-
};
100-
10196
/**
10297
* User actions union type
10398
*/
@@ -123,5 +118,4 @@ export type UserAction =
123118
| SetGasEducationCarouselSeenAction
124119
| SetAppThemeAction
125120
| CheckedAuthAction
126-
| SetAppServicesReadyAction
127-
| SetMetaMetricsUISeenAction;
121+
| SetAppServicesReadyAction;

app/components/Nav/App/App.test.tsx

Lines changed: 69 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ import { RootState } from '../../../reducers';
1111
import StorageWrapper from '../../../store/storage-wrapper';
1212
import { Authentication } from '../../../core';
1313
import Routes from '../../../constants/navigation/Routes';
14+
import {
15+
OPTIN_META_METRICS_UI_SEEN,
16+
EXISTING_USER,
17+
} from '../../../constants/storage';
1418
import { strings } from '../../../../locales/i18n';
1519
import { NavigationContainer } from '@react-navigation/native';
1620
import configureMockStore from 'redux-mock-store';
@@ -20,7 +24,6 @@ import { mockTheme, ThemeContext } from '../../../util/theme';
2024
const initialState: DeepPartial<RootState> = {
2125
user: {
2226
userLoggedIn: true,
23-
isMetaMetricsUISeen: true,
2427
},
2528
engine: {
2629
backgroundState,
@@ -83,6 +86,14 @@ const mockMetrics = {
8386
addTraitsToUser: jest.fn(),
8487
};
8588

89+
// Mock Authentication module
90+
jest.mock('../../../core', () => ({
91+
Authentication: {
92+
appTriggeredAuth: jest.fn().mockResolvedValue(undefined),
93+
lockApp: jest.fn(),
94+
},
95+
}));
96+
8697
// Need to mock this module since it uses store.getState, which interferes with the mocks from this test file.
8798
jest.mock(
8899
'../../../util/metrics/UserSettingsAnalyticsMetaData/generateUserProfileAnalyticsMetaData',
@@ -94,6 +105,16 @@ jest.mock(
94105
() => jest.fn().mockReturnValue({ deviceProp: 'Device value' }),
95106
);
96107

108+
// Mock essential dependencies
109+
jest.mock('react-native-branch', () => ({
110+
subscribe: jest.fn(),
111+
getLatestReferringParams: jest.fn().mockResolvedValue({}),
112+
}));
113+
114+
jest.mock('react-native-device-info', () => ({
115+
getVersion: jest.fn().mockReturnValue('1.0.0'),
116+
}));
117+
97118
(MetaMetrics.getInstance as jest.Mock).mockReturnValue(mockMetrics);
98119

99120
describe('App', () => {
@@ -122,7 +143,12 @@ describe('App', () => {
122143

123144
describe('Authentication flow logic', () => {
124145
it('navigates to onboarding when user does not exist', async () => {
125-
jest.spyOn(StorageWrapper, 'getItem').mockResolvedValue(null);
146+
jest.spyOn(StorageWrapper, 'getItem').mockImplementation(async (key) => {
147+
if (key === EXISTING_USER) {
148+
return null; // User does not exist
149+
}
150+
return null; // Default for other keys
151+
});
126152
renderScreen(App, { name: 'App' }, { state: initialState });
127153
await waitFor(() => {
128154
expect(mockReset).toHaveBeenCalledWith({
@@ -131,7 +157,15 @@ describe('App', () => {
131157
});
132158
});
133159
it('navigates to login when user exists and logs in', async () => {
134-
jest.spyOn(StorageWrapper, 'getItem').mockResolvedValue(true);
160+
jest.spyOn(StorageWrapper, 'getItem').mockImplementation(async (key) => {
161+
if (key === EXISTING_USER) {
162+
return true; // User exists
163+
}
164+
if (key === OPTIN_META_METRICS_UI_SEEN) {
165+
return true; // OptinMetrics UI has been seen
166+
}
167+
return null; // Default for other keys
168+
});
135169
jest.spyOn(Authentication, 'appTriggeredAuth').mockResolvedValue();
136170
renderScreen(App, { name: 'App' }, { state: initialState });
137171
await waitFor(() => {
@@ -141,30 +175,47 @@ describe('App', () => {
141175
});
142176
});
143177

144-
it('navigates to OptinMetrics when user exists and isMetaMetricsUISeen is false', async () => {
145-
jest.spyOn(StorageWrapper, 'getItem').mockResolvedValue(true);
146-
jest.spyOn(Authentication, 'appTriggeredAuth').mockResolvedValue();
178+
it('navigates to OptinMetrics when user exists and OptinMetaMetricsUISeen is false', async () => {
179+
// Mock StorageWrapper.getItem to return different values based on the key
180+
jest.spyOn(StorageWrapper, 'getItem').mockImplementation(async (key) => {
181+
if (key === EXISTING_USER) {
182+
return true; // User exists
183+
}
184+
if (key === OPTIN_META_METRICS_UI_SEEN) {
185+
return false; // OptinMetrics UI has not been seen
186+
}
187+
return null; // Default for other keys
188+
});
189+
147190
renderScreen(
148191
App,
149192
{ name: 'App' },
150193
{
151194
state: {
152195
...initialState,
153-
user: { ...initialState.user, isMetaMetricsUISeen: false },
154196
},
155197
},
156198
);
157-
await waitFor(() => {
158-
expect(mockNavigate).toHaveBeenCalledWith(Routes.ONBOARDING.ROOT_NAV, {
159-
screen: Routes.ONBOARDING.NAV,
160-
params: {
161-
screen: Routes.ONBOARDING.OPTIN_METRICS,
162-
params: {
163-
onContinue: expect.any(Function),
164-
},
165-
},
166-
});
167-
});
199+
200+
// Wait a bit longer and add debugging
201+
await waitFor(
202+
() => {
203+
expect(mockReset).toHaveBeenCalledWith({
204+
routes: [
205+
{
206+
name: 'OnboardingRootNav',
207+
params: {
208+
screen: 'OnboardingNav',
209+
params: {
210+
screen: 'OptinMetrics',
211+
},
212+
},
213+
},
214+
],
215+
});
216+
},
217+
{ timeout: 5000 },
218+
);
168219
});
169220
});
170221

app/components/Nav/App/App.tsx

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import {
3232
CURRENT_APP_VERSION,
3333
EXISTING_USER,
3434
LAST_APP_VERSION,
35+
OPTIN_META_METRICS_UI_SEEN,
3536
} from '../../../constants/storage';
3637
import { getVersion } from 'react-native-device-info';
3738
import { Authentication } from '../../../core/';
@@ -146,7 +147,6 @@ import RevealSRP from '../../Views/MultichainAccounts/sheets/RevealSRP';
146147
import { DeepLinkModal } from '../../UI/DeepLinkModal';
147148
import { checkForDeeplink } from '../../../actions/user';
148149
import { WalletDetails } from '../../Views/MultichainAccounts/WalletDetails/WalletDetails';
149-
import { RootState } from '../../../reducers';
150150
import { SmartAccountUpdateModal } from '../../Views/confirmations/components/smart-account-update-modal';
151151

152152
const clearStackNavigatorOptions = {
@@ -829,10 +829,6 @@ const App: React.FC = () => {
829829
const sdkInit = useRef<boolean | undefined>(undefined);
830830
const isFirstRender = useRef(true);
831831

832-
const isMetaMetricsUISeen = useSelector(
833-
(state: RootState) => state.user.isMetaMetricsUISeen,
834-
);
835-
836832
if (isFirstRender.current) {
837833
trace({
838834
name: TraceName.NavInit,
@@ -865,19 +861,25 @@ const App: React.FC = () => {
865861
},
866862
);
867863

868-
if (!isMetaMetricsUISeen) {
869-
navigation.navigate(Routes.ONBOARDING.ROOT_NAV, {
870-
screen: Routes.ONBOARDING.NAV,
871-
params: {
872-
screen: Routes.ONBOARDING.OPTIN_METRICS,
873-
params: {
874-
onContinue: () =>
875-
navigation.reset({
876-
routes: [{ name: Routes.ONBOARDING.HOME_NAV }],
877-
}),
864+
const isOptinMetaMetricsUISeen = await StorageWrapper.getItem(
865+
OPTIN_META_METRICS_UI_SEEN,
866+
);
867+
868+
if (!isOptinMetaMetricsUISeen) {
869+
const resetParams = {
870+
routes: [
871+
{
872+
name: Routes.ONBOARDING.ROOT_NAV,
873+
params: {
874+
screen: Routes.ONBOARDING.NAV,
875+
params: {
876+
screen: Routes.ONBOARDING.OPTIN_METRICS,
877+
},
878+
},
878879
},
879-
},
880-
});
880+
],
881+
};
882+
navigation.reset(resetParams);
881883
} else {
882884
navigation.reset({
883885
routes: [{ name: Routes.ONBOARDING.HOME_NAV }],
@@ -903,7 +905,7 @@ const App: React.FC = () => {
903905
appTriggeredAuth().catch((error) => {
904906
Logger.error(error, 'App: Error in appTriggeredAuth');
905907
});
906-
}, [navigation, isMetaMetricsUISeen]);
908+
}, [navigation]);
907909

908910
const handleDeeplink = useCallback(
909911
({ uri }: { uri?: string }) => {

app/components/UI/CollectibleContracts/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ import { useNftDetectionChainIds } from '../../hooks/useNftDetectionChainIds';
6363
import Logger from '../../../util/Logger';
6464
import { prepareNftDetectionEvents } from '../../../util/assets';
6565
import { endTrace, trace, TraceName } from '../../../util/trace';
66+
import { isNonEvmChainId } from '../../../core/Multichain/utils';
6667

6768
const createStyles = (colors) =>
6869
StyleSheet.create({
@@ -192,6 +193,7 @@ const CollectibleContracts = ({
192193
const allNetworkClientIds = useMemo(
193194
() =>
194195
Object.keys(tokenNetworkFilter).flatMap((chainId) => {
196+
if (isNonEvmChainId(chainId)) return [];
195197
const entry = allNetworks[chainId];
196198
if (!entry) {
197199
return [];

0 commit comments

Comments
 (0)