Skip to content

Commit 934aff0

Browse files
authored
refactor: update network switching metrics to include chain ID and custom network status (MetaMask#23613)
<!-- 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** This PR adds additional properties to the NETWORK_SWITCHED analytics event to improve network switching tracking. The changes include: 1. Adding from_network and to_network as chain IDs (hex format) instead of network names 2. Adding custom_network boolean flag to indicate if the target network is a custom (non-popular) network Removing the selectedNetworkName parameter from useSwitchNetworks hook as it's no longer needed These changes apply to network switching from: - Network Selector modal - Network Permissions Connected component (dApp permission flow) - RPC method calls (wallet_switchEthereumChain) ## **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` 3. 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: https://consensyssoftware.atlassian.net/browse/TMCU-213 ## **Manual testing steps** ```gherkin Feature: Network Switched Analytics Event Scenario: user switches network from Network Selector Given user is on any screen with network selector accessible When user opens the network selector and switches to a different network Then the NETWORK_SWITCHED event should contain chain_id, from_network, to_network, and custom_network properties Scenario: user switches network via dApp permission Given user is connected to a dApp with network permissions When user switches network through the network permissions modal Then the NETWORK_SWITCHED event should contain chain_id, from_network (hex), to_network (hex), and custom_network (boolean) Scenario: dApp requests network switch via RPC Given user is connected to a dApp When the dApp calls wallet_switchEthereumChain Then the NETWORK_SWITCHED event should include from_network, to_network, and custom_network properties ``` ## **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. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Unifies NETWORK_SWITCHED analytics to report from/to chain IDs and a custom_network flag across UI flows and RPC, with tests updated accordingly. > > - **Analytics/metrics** > - Standardize `MetaMetricsEvents.NETWORK_SWITCHED` properties across network switching flows: > - `from_network` and `to_network` now use chain IDs (hex) instead of names. > - Add `custom_network` boolean based on `POPULAR_NETWORK_CHAIN_IDS`. > - Ensure `chain_id` reflects the target chain (decimal where applicable). > - Apply changes in: > - `app/components/Views/AccountPermissions/.../NetworkPermissionsConnected.tsx` (remove `selectProviderConfig`; track using `evmChainId` → `targetChainId`). > - `app/components/Views/NetworkSelector/useSwitchNetworks.ts` (remove `selectedNetworkName`; track with `selectedChainId` → `chainId`/built-ins; add popularity check). > - `app/core/RPCMethods/lib/ethereum-chain-utils.js` (include `from_network`, `to_network`, `custom_network`). > - **Tests** > - Update `ethereum-chain-utils.test.ts` to assert new analytics fields (`from_network`, `to_network`, `custom_network`). > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit df07c0b. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
1 parent e47bcb5 commit 934aff0

4 files changed

Lines changed: 27 additions & 19 deletions

File tree

app/components/Views/AccountPermissions/NetworkPermissionsConnected/NetworkPermissionsConnected.tsx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ import { AccountPermissionsScreens } from '../AccountPermissions.types';
1111
import { MetaMetricsEvents } from '../../../../core/Analytics';
1212
import Routes from '../../../../constants/navigation/Routes';
1313
import {
14-
selectProviderConfig,
15-
ProviderConfig,
1614
selectEvmChainId,
1715
selectEvmNetworkConfigurationsByChainId,
1816
} from '../../../../selectors/networkController';
@@ -48,6 +46,7 @@ import { getCaip25Caveat } from '../../../../core/Permissions';
4846
import { getPermittedEthChainIds } from '@metamask/chain-agnostic-permission';
4947
import { toHex } from '@metamask/controller-utils';
5048
import { parseCaipChainId } from '@metamask/utils';
49+
import { POPULAR_NETWORK_CHAIN_IDS } from '../../../../constants/popular-networks';
5150

5251
// Needs to be updated to handle non-evm
5352
const NetworkPermissionsConnected = ({
@@ -59,7 +58,6 @@ const NetworkPermissionsConnected = ({
5958
const { navigate } = useNavigation();
6059
const { trackEvent, createEventBuilder } = useMetrics();
6160

62-
const providerConfig: ProviderConfig = useSelector(selectProviderConfig);
6361
const evmChainId = useSelector(selectEvmChainId);
6462
const evmCaipChainId = `eip155:${parseInt(evmChainId, 16)}`;
6563

@@ -141,12 +139,15 @@ const NetworkPermissionsConnected = ({
141139
const theNetworkName = handleNetworkSwitch(reference);
142140

143141
if (theNetworkName) {
142+
const targetChainId = toHex(reference);
144143
trackEvent(
145144
createEventBuilder(MetaMetricsEvents.NETWORK_SWITCHED)
146145
.addProperties({
147146
chain_id: reference,
148-
from_network: providerConfig?.nickname || theNetworkName,
149-
to_network: theNetworkName,
147+
from_network: evmChainId,
148+
to_network: targetChainId,
149+
custom_network:
150+
!POPULAR_NETWORK_CHAIN_IDS.has(targetChainId),
150151
})
151152
.build(),
152153
);

app/components/Views/NetworkSelector/useSwitchNetworks.ts

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ export function useSwitchNetworks({
6666
domainIsConnectedDapp = false,
6767
origin = '',
6868
selectedChainId,
69-
selectedNetworkName,
7069
dismissModal,
7170
closeRpcModal,
7271
parentSpan,
@@ -109,12 +108,8 @@ export function useSwitchNetworks({
109108

110109
const { MultichainNetworkController, SelectedNetworkController } =
111110
Engine.context;
112-
const {
113-
name: nickname,
114-
chainId,
115-
rpcEndpoints,
116-
defaultRpcEndpointIndex,
117-
} = networkConfiguration;
111+
const { chainId, rpcEndpoints, defaultRpcEndpointIndex } =
112+
networkConfiguration;
118113

119114
const networkConfigurationId =
120115
rpcEndpoints[defaultRpcEndpointIndex].networkClientId;
@@ -154,16 +149,17 @@ export function useSwitchNetworks({
154149
createEventBuilder(MetaMetricsEvents.NETWORK_SWITCHED)
155150
.addProperties({
156151
chain_id: getDecimalChainId(chainId),
157-
from_network: selectedNetworkName,
158-
to_network: nickname,
152+
from_network: selectedChainId,
153+
to_network: chainId,
154+
custom_network: !POPULAR_NETWORK_CHAIN_IDS.has(chainId),
159155
})
160156
.build(),
161157
);
162158
},
163159
[
164160
domainIsConnectedDapp,
165161
origin,
166-
selectedNetworkName,
162+
selectedChainId,
167163
trackEvent,
168164
createEventBuilder,
169165
parentSpan,
@@ -225,12 +221,14 @@ export function useSwitchNetworks({
225221
endTrace({ name: TraceName.SwitchBuiltInNetwork });
226222
endTrace({ name: TraceName.NetworkSwitch });
227223

224+
const toChainId = BUILT_IN_NETWORKS[type].chainId;
228225
trackEvent(
229226
createEventBuilder(MetaMetricsEvents.NETWORK_SWITCHED)
230227
.addProperties({
231-
chain_id: getDecimalChainId(selectedChainId),
232-
from_network: selectedNetworkName,
233-
to_network: type,
228+
chain_id: getDecimalChainId(toChainId),
229+
from_network: selectedChainId,
230+
to_network: toChainId,
231+
custom_network: !POPULAR_NETWORK_CHAIN_IDS.has(toChainId),
234232
})
235233
.build(),
236234
);
@@ -241,7 +239,6 @@ export function useSwitchNetworks({
241239
networkConfigurations,
242240
setTokenNetworkFilter,
243241
selectedChainId,
244-
selectedNetworkName,
245242
trackEvent,
246243
createEventBuilder,
247244
parentSpan,

app/core/RPCMethods/lib/ethereum-chain-utils.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { MetaMetrics, MetaMetricsEvents } from '../../../core/Analytics';
1515
import { MetricsEventBuilder } from '../../../core/Analytics/MetricsEventBuilder';
1616
import Engine from '../../Engine';
1717
import { isSnapId } from '@metamask/snaps-utils';
18+
import { POPULAR_NETWORK_CHAIN_IDS } from '../../../constants/popular-networks';
1819

1920
const EVM_NATIVE_TOKEN_DECIMALS = 18;
2021

@@ -278,10 +279,14 @@ export async function switchToNetwork({
278279
networkClientId,
279280
);
280281

282+
const fromChainId = hooks.fromNetworkConfiguration?.chainId;
281283
const analyticsParams = {
282284
chain_id: getDecimalChainId(chainId),
283285
source: 'Custom Network API',
284286
symbol: nativeCurrency || 'ETH',
287+
from_network: fromChainId,
288+
to_network: chainId,
289+
custom_network: !POPULAR_NETWORK_CHAIN_IDS.has(chainId),
285290
...analytics,
286291
};
287292

app/core/RPCMethods/lib/ethereum-chain-utils.test.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,14 @@ describe('switchToNetwork', () => {
3939
build: jest.fn().mockReturnValue(mockMetricsBuilderBuild),
4040
});
4141

42+
const fromChainId = '0x89';
4243
const mockHooks = {
4344
getCaveat: jest
4445
.fn()
4546
.mockReturnValue({ value: getDefaultCaip25CaveatValue() }),
4647
requestPermittedChainsPermissionIncrementalForOrigin: jest.fn(),
4748
hasApprovalRequestsForOrigin: jest.fn(),
49+
fromNetworkConfiguration: { chainId: fromChainId },
4850
};
4951

5052
const chainId = '0x1';
@@ -82,6 +84,9 @@ describe('switchToNetwork', () => {
8284
chain_id: '1',
8385
source: 'Custom Network API',
8486
symbol: 'ETH',
87+
from_network: fromChainId,
88+
to_network: chainId,
89+
custom_network: false,
8590
test: 'test',
8691
});
8792
expect(mockTrackEvent).toHaveBeenCalledWith(mockMetricsBuilderBuild);

0 commit comments

Comments
 (0)