Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
1ec078f
fix: initialize network enablement controller to get correct namespac…
vinnyhoward Sep 3, 2025
e272565
chore: add patch for btc state fix
vinnyhoward Sep 3, 2025
0197c40
fix: background init state for test
vinnyhoward Sep 3, 2025
bc9a83c
fix: update tests
vinnyhoward Sep 3, 2025
52e990d
fix: update default state for btc with testnet
vinnyhoward Sep 4, 2025
cd1822f
fix: update btc testnet enabledMap to true
vinnyhoward Sep 4, 2025
e9079a0
feat: enable btc testnet selection and filtering
vinnyhoward Sep 5, 2025
3d63e19
fix: btc testnets
aganglada Sep 5, 2025
a7e4c31
fix: snapshots
vinnyhoward Sep 8, 2025
77989aa
fix: update patch
vinnyhoward Sep 9, 2025
71a7650
Merge branch 'main' into fix-19201-missing-btc-network-enablement
vinnyhoward Sep 9, 2025
4da43f5
Merge branch 'fix-19201-missing-btc-network-enablement' into fix-1920…
aganglada Sep 9, 2025
ac21c98
chore: remove filtering tokens logic
aganglada Sep 9, 2025
25f7e75
Merge branch 'main' into fix-19201-missing-btc-network-enablement-3
zone-live Sep 12, 2025
385d904
chore: remove unnecessary patch
zone-live Sep 12, 2025
04e926e
chore: small typo fix
zone-live Sep 12, 2025
7cda5df
chore: reset file
zone-live Sep 12, 2025
869e306
chore: code fence fix
zone-live Sep 12, 2025
06053c7
chore: lint fix
zone-live Sep 12, 2025
85f3c6d
chore: test update
zone-live Sep 12, 2025
d5f205d
chore: remoe unnecessary test
zone-live Sep 12, 2025
e9b6bff
chore: test update
zone-live Sep 12, 2025
c943413
chore: prettier
zone-live Sep 12, 2025
d058113
chore: review improv
zone-live Sep 15, 2025
ce7c6ec
chore: update
zone-live Sep 15, 2025
00f3c49
Merge branch 'main' into fix-19201-missing-btc-network-enablement-3
zone-live Sep 15, 2025
71439a7
chore: update to add BTC to popular networks as well
zone-live Sep 15, 2025
f1ea281
Update app/selectors/networkController.ts
zone-live Sep 15, 2025
d38c390
chore: clean up
zone-live Sep 15, 2025
f8590f5
Merge branch 'fix-19201-missing-btc-network-enablement-3' of github.c…
zone-live Sep 15, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import CustomNetworkSelector from './CustomNetworkSelector';
import { CustomNetworkItem } from './CustomNetworkSelector.types';
import { selectMultichainAccountsState2Enabled } from '../../../selectors/featureFlagController/multichainAccounts/enabledMultichainAccounts';
import { InternalAccount } from '@metamask/keyring-internal-api';
import { selectIsEvmNetworkSelected } from '../../../selectors/multichainNetworkController';

jest.mock('@react-navigation/native', () => ({
useNavigation: jest.fn(),
Expand Down Expand Up @@ -142,6 +143,10 @@ jest.mock('@shopify/flash-list', () => {
};
});

jest.mock('../../../selectors/multichainNetworkController', () => ({
selectIsEvmNetworkSelected: jest.fn(),
}));

// Mock store setup
const mockStore = createStore(() => ({
featureFlags: {
Expand Down Expand Up @@ -178,7 +183,10 @@ describe('CustomNetworkSelector', () => {
typeof useNetworksToUse
>;
const mockUseSelector = jest.mocked(useSelector);

const mockSelectIsEvmNetworkSelected =
selectIsEvmNetworkSelected as jest.MockedFunction<
typeof selectIsEvmNetworkSelected
>;
const mockNetworks: CustomNetworkItem[] = [
{
id: 'eip155:137',
Expand Down Expand Up @@ -262,10 +270,15 @@ describe('CustomNetworkSelector', () => {
areAllSolanaNetworksSelected: false,
});

mockSelectIsEvmNetworkSelected.mockReturnValue(true);

mockUseSelector.mockImplementation((selector) => {
if (selector === selectMultichainAccountsState2Enabled) {
return true;
}
if (selector === mockSelectIsEvmNetworkSelected) {
return true;
}
return undefined;
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { useNavigation } from '@react-navigation/native';
import { parseCaipChainId } from '@metamask/utils';
import { toHex } from '@metamask/controller-utils';
import { useSelector } from 'react-redux';

// external dependencies
import { strings } from '../../../../locales/i18n';
Expand Down Expand Up @@ -41,6 +42,7 @@ import {
CustomNetworkItem,
CustomNetworkSelectorProps,
} from './CustomNetworkSelector.types';
import { selectIsEvmNetworkSelected } from '../../../selectors/multichainNetworkController';
import { useNetworksToUse } from '../../hooks/useNetworksToUse/useNetworksToUse';

const CustomNetworkSelector = ({
Expand All @@ -51,6 +53,7 @@ const CustomNetworkSelector = ({
const { styles } = useStyles(createStyles, { colors });
const { navigate } = useNavigation();
const safeAreaInsets = useSafeAreaInsets();
const isEvmSelected = useSelector(selectIsEvmNetworkSelected);

// Use custom hooks for network management
const { networks, areAllNetworksSelected } = useNetworksByNamespace({
Expand Down Expand Up @@ -78,7 +81,7 @@ const CustomNetworkSelector = ({
({ item }) => {
const { name, caipChainId, networkTypeOrRpcUrl, isSelected } = item;
const rawChainId = parseCaipChainId(caipChainId).reference;
const chainId = toHex(rawChainId);
const chainId = isEvmSelected ? toHex(rawChainId) : rawChainId;

const handlePress = async () => {
await selectCustomNetwork(caipChainId, dismissModal);
Expand Down Expand Up @@ -115,7 +118,7 @@ const CustomNetworkSelector = ({
</View>
);
},
[selectCustomNetwork, openModal, dismissModal],
[selectCustomNetwork, openModal, dismissModal, isEvmSelected],
);

const renderFooter = useCallback(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import { formatChainIdToCaip } from '@metamask/bridge-controller';
import { debounce, type DebouncedFunc } from 'lodash';
import { useStyles } from '../../../component-library/hooks/index.ts';
import { isTestNet } from '../../../util/networks/index.js';
import { selectEvmChainId } from '../../../selectors/networkController';
import { selectChainId } from '../../../selectors/networkController';
import { selectIsEvmNetworkSelected } from '../../../selectors/multichainNetworkController';
import NetworkMultiSelectorList from './NetworkMultiSelectorList';
import {
NetworkMultiSelectorListProps,
Expand Down Expand Up @@ -78,6 +79,11 @@ jest.mock('../../../util/device/index.js', () => ({

jest.mock('../../../selectors/networkController', () => ({
selectEvmChainId: jest.fn(),
selectChainId: jest.fn(),
}));

jest.mock('../../../selectors/multichainNetworkController', () => ({
selectIsEvmNetworkSelected: jest.fn(),
}));

// Mock component library components
Expand Down Expand Up @@ -149,9 +155,13 @@ describe('NetworkMultiSelectorList', () => {
const mockDebounce = debounce as jest.MockedFunction<typeof debounce>;
const mockUseStyles = useStyles as jest.MockedFunction<typeof useStyles>;
const mockIsTestNet = isTestNet as jest.MockedFunction<typeof isTestNet>;
const mockSelectEvmChainId = selectEvmChainId as jest.MockedFunction<
typeof selectEvmChainId
const mockSelectChainId = selectChainId as jest.MockedFunction<
typeof selectChainId
>;
const mockSelectIsEvmNetworkSelected =
selectIsEvmNetworkSelected as jest.MockedFunction<
typeof selectIsEvmNetworkSelected
>;

const mockOnSelectNetwork = jest.fn();
const mockOpenModal = jest.fn();
Expand Down Expand Up @@ -194,6 +204,7 @@ describe('NetworkMultiSelectorList', () => {
jest.clearAllMocks();

mockUseSelector.mockReturnValue('0x1');
mockSelectIsEvmNetworkSelected.mockReturnValue(true);
mockUseSafeAreaInsets.mockReturnValue({
top: 0,
right: 0,
Expand Down Expand Up @@ -232,9 +243,9 @@ describe('NetworkMultiSelectorList', () => {
expect(mockUseSafeAreaInsets).toHaveBeenCalled();
});

it('calls useSelector with selectEvmChainId', () => {
it('calls useSelector with selectChainId', () => {
render(<NetworkMultiSelectorList {...defaultProps} />);
expect(mockUseSelector).toHaveBeenCalledWith(mockSelectEvmChainId);
expect(mockUseSelector).toHaveBeenCalledWith(mockSelectChainId);
});

it('calls useStyles with styleSheet', () => {
Expand Down Expand Up @@ -361,6 +372,21 @@ describe('NetworkMultiSelectorList', () => {
reference: chainId.split(':')[1],
}));

mockToHex.mockClear();
mockUseSelector.mockClear();

// Set useSelector to return different values based on the selector
mockUseSelector.mockImplementation((selector) => {
if (selector === mockSelectChainId) {
return '0x1';
}
if (selector === mockSelectIsEvmNetworkSelected) {
// return false for isEvmSelected
return false;
}
return undefined;
});

const props = { ...defaultProps, networks: [solanaNetwork] };
render(<NetworkMultiSelectorList {...props} />);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import Cell, {
} from '../../../component-library/components/Cells/Cell/index.ts';
import { isTestNet } from '../../../util/networks/index.js';
import Device from '../../../util/device/index.js';
import { selectEvmChainId } from '../../../selectors/networkController';
import { selectChainId } from '../../../selectors/networkController';

// Internal dependencies.
import {
Expand All @@ -48,6 +48,7 @@ import {
ITEM_TYPE_NETWORK,
SELECT_ALL_NETWORKS_SECTION_ID,
} from './NetworkMultiSelectorList.constants';
import { selectIsEvmNetworkSelected } from '../../../selectors/multichainNetworkController';

const SELECTION_DEBOUNCE_DELAY = 150;

Expand Down Expand Up @@ -76,7 +77,8 @@ const NetworkMultiSelectList = ({
const networkListRef = useRef<any>(null);
const networksLengthRef = useRef<number>(0);
const safeAreaInsets = useSafeAreaInsets();
const selectedChainId = useSelector(selectEvmChainId);
const selectedChainId = useSelector(selectChainId);
const isEvmSelected = useSelector(selectIsEvmNetworkSelected);
const selectedChainIdCaip = formatChainIdToCaip(selectedChainId);

const { styles } = useStyles(styleSheet, {});
Expand All @@ -85,10 +87,10 @@ const NetworkMultiSelectList = ({
(): ProcessedNetwork[] =>
networks.map((network) => {
const parsedCaipChainId = parseCaipChainId(network.caipChainId);
const chainId =
parsedCaipChainId.namespace !== 'solana'
? toHex(parsedCaipChainId.reference)
: '';
const chainId = isEvmSelected
? toHex(parsedCaipChainId.reference)
: parsedCaipChainId.reference;

return {
...network,
chainId,
Expand All @@ -98,7 +100,7 @@ const NetworkMultiSelectList = ({
isSelected: areAllNetworksSelected ? false : network.isSelected,
};
}),
[areAllNetworksSelected, networks],
[areAllNetworksSelected, networks, isEvmSelected],
);

const combinedData: NetworkListItem[] = useMemo(() => {
Expand All @@ -111,7 +113,7 @@ const NetworkMultiSelectList = ({
data.push(...filteredNetworks);
}

if (selectAllNetworksComponent) {
if (selectAllNetworksComponent && isEvmSelected) {
data.unshift({
id: SELECT_ALL_NETWORKS_SECTION_ID,
type: NetworkListItemType.SelectAllNetworksListItem,
Expand All @@ -132,7 +134,9 @@ const NetworkMultiSelectList = ({
processedNetworks,
additionalNetworksComponent,
selectAllNetworksComponent,
isEvmSelected,
]);

const contentContainerStyle = useMemo(
() => ({
paddingBottom:
Expand Down Expand Up @@ -241,7 +245,6 @@ const NetworkMultiSelectList = ({

const isDisabled = isLoading || isSelectionDisabled;
const showButtonIcon = Boolean(networkTypeOrRpcUrl);

return (
<View testID={`${name}-${isSelected ? 'selected' : 'not-selected'}`}>
<Cell
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -397,21 +397,6 @@ describe('TokenListControlBar', () => {

expect(goToAddToken).toHaveBeenCalled();
});

it('should not call handleFilterControls when EVM is not selected', () => {
// Ensure EVM is not selected
mockSelectIsEvmNetworkSelected.mockReturnValue(false);
mockSelectChainId.mockReturnValue(
'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',
);

const { getByTestId } = renderComponent();

const filterButton = getByTestId('token-network-filter');
fireEvent.press(filterButton);

expect(mockNavigate).not.toHaveBeenCalled();
});
});

describe('Button states', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export const TokenListControlBar = ({
<BaseControlBar
networkFilterTestId={WalletViewSelectorsIDs.TOKEN_NETWORK_FILTER}
additionalButtons={additionalButtons}
useEvmSelectionLogic
useEvmSelectionLogic={isEvmSelected}
customWrapper="outer"
/>
);
Expand Down
15 changes: 13 additions & 2 deletions app/components/hooks/useCurrentNetworkInfo.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { useMemo, useCallback } from 'react';
import { useSelector } from 'react-redux';
import { KnownCaipNamespace } from '@metamask/utils';
import { formatChainIdToCaip } from '@metamask/bridge-controller';
import { selectNetworkConfigurationsByCaipChainId } from '../../selectors/networkController';
import {
selectNetworkConfigurationsByCaipChainId,
selectChainId,
} from '../../selectors/networkController';
import { selectIsEvmNetworkSelected } from '../../selectors/multichainNetworkController';
import { useNetworkEnablement } from './useNetworkEnablement/useNetworkEnablement';
import { selectMultichainAccountsState2Enabled } from '../../selectors/featureFlagController/multichainAccounts';
Expand All @@ -28,6 +32,9 @@ export const useCurrentNetworkInfo = (): CurrentNetworkInfo => {
selectNetworkConfigurationsByCaipChainId,
);
const isEvmSelected = useSelector(selectIsEvmNetworkSelected);
const selectedChainId = useSelector(selectChainId);
const isSolanaSelected =
selectedChainId?.includes(KnownCaipNamespace.Solana) ?? false;
const isMultichainAccountsState2Enabled = useSelector(
selectMultichainAccountsState2Enabled,
);
Expand Down Expand Up @@ -87,7 +94,11 @@ export const useCurrentNetworkInfo = (): CurrentNetworkInfo => {
[enabledNetworks, networksByCaipChainId],
);

const isDisabled = !isEvmSelected && !isMultichainAccountsState2Enabled;
let isDisabled: boolean = Boolean(!isEvmSelected);
// We don't have Solana testnet networks, so we disable the network selector if Solana is selected
// TODO: Come back when we have Solana devnet available
isDisabled = Boolean(isSolanaSelected);

const hasEnabledNetworks = enabledNetworks.length > 0;

return {
Expand Down
Loading
Loading