From 5d2dd4503903826d66d070ae657ecddffcf514fd Mon Sep 17 00:00:00 2001 From: Prithpal Sooriya Date: Fri, 14 Jun 2024 12:26:54 +0100 Subject: [PATCH] fix: notification detail network fee broke application (#25315) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## **Description** Yeah, due to some type assertions (evil), we did not receive a correct value expected. Due to this we ended up performing a `.split` on an undefined... then crash. This adds some safer logic and also fixes the area that call the function with the wrong inputs. A separate PR will be ready that fixes these bad type assertions. [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/25315?quickstart=1) ## **Related issues** Fixes: ## **Manual testing steps** 1. Create a MATIC send/receive notification 2. Open details 3. See crash ## **Screenshots/Recordings** ![image](https://github.com/MetaMask/metamask-extension/assets/17534261/4f4bb77d-dabd-4226-983a-b6d6ff2bb6b5) ### **Before** ### **After** ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.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-extension/blob/develop/.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. --- ...ification-detail-block-explorer-button.tsx | 2 +- ui/helpers/utils/notification.util.ts | 33 +++++++++---------- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/ui/components/multichain/notification-detail-block-explorer-button/notification-detail-block-explorer-button.tsx b/ui/components/multichain/notification-detail-block-explorer-button/notification-detail-block-explorer-button.tsx index 572762578d4b..23237a70a0c7 100644 --- a/ui/components/multichain/notification-detail-block-explorer-button/notification-detail-block-explorer-button.tsx +++ b/ui/components/multichain/notification-detail-block-explorer-button/notification-detail-block-explorer-button.tsx @@ -27,7 +27,7 @@ export const NotificationDetailBlockExplorerButton = ({ const chainIdHex = decimalToHex(chainId); const { nativeBlockExplorerUrl } = getNetworkDetailsByChainId( - `0x${chainId}` as keyof typeof CHAIN_IDS, + `0x${chainIdHex}` as keyof typeof CHAIN_IDS, ); const defaultNetworks: NetworkConfiguration[] = useSelector(getAllNetworks); diff --git a/ui/helpers/utils/notification.util.ts b/ui/helpers/utils/notification.util.ts index 31be80d4d8de..0ecafa5f0bcb 100644 --- a/ui/helpers/utils/notification.util.ts +++ b/ui/helpers/utils/notification.util.ts @@ -267,8 +267,8 @@ export function getNetworkDetailsByChainId(chainId?: keyof typeof CHAIN_IDS): { nativeBlockExplorerUrl?: string; } { const fullNativeCurrencyName = - NETWORK_TO_NAME_MAP[chainId as keyof typeof NETWORK_TO_NAME_MAP]; - const nativeCurrencyName = fullNativeCurrencyName.split(' ')[0]; + NETWORK_TO_NAME_MAP[chainId as keyof typeof NETWORK_TO_NAME_MAP] ?? ''; + const nativeCurrencyName = fullNativeCurrencyName.split(' ')[0] ?? ''; const nativeCurrencySymbol = CHAIN_ID_TO_CURRENCY_SYMBOL_MAP[ chainId as keyof typeof CHAIN_ID_TO_CURRENCY_SYMBOL_MAP @@ -320,6 +320,8 @@ export function formatIsoDateString(isoDateString: string) { return formattedDate; } +export type HexChainId = (typeof CHAIN_IDS)[keyof typeof CHAIN_IDS]; + /** * Retrieves the RPC URL associated with a given chain ID. * @@ -329,10 +331,8 @@ export function formatIsoDateString(isoDateString: string) { * @param chainId - The chain ID for which the RPC URL is required. * @returns The RPC URL associated with the given chain ID, or undefined if no match is found. */ -export function getRpcUrlByChainId(chainId: keyof typeof CHAIN_IDS): string { - const rpc = FEATURED_RPCS.find( - (rpcItem) => rpcItem.chainId === CHAIN_IDS[chainId], - ); +export function getRpcUrlByChainId(chainId: HexChainId): string { + const rpc = FEATURED_RPCS.find((rpcItem) => rpcItem.chainId === chainId); // If rpc is found, return its URL. Otherwise, return a default URL based on the chainId. if (rpc) { @@ -340,19 +340,19 @@ export function getRpcUrlByChainId(chainId: keyof typeof CHAIN_IDS): string { } // Fallback RPC URLs based on the chainId switch (chainId) { - case 'MAINNET': + case CHAIN_IDS.MAINNET: return MAINNET_RPC_URL; - case 'GOERLI': + case CHAIN_IDS.GOERLI: return GOERLI_RPC_URL; - case 'SEPOLIA': + case CHAIN_IDS.SEPOLIA: return SEPOLIA_RPC_URL; - case 'LINEA_GOERLI': + case CHAIN_IDS.LINEA_GOERLI: return LINEA_GOERLI_RPC_URL; - case 'LINEA_SEPOLIA': + case CHAIN_IDS.LINEA_SEPOLIA: return LINEA_SEPOLIA_RPC_URL; - case 'LINEA_MAINNET': + case CHAIN_IDS.LINEA_MAINNET: return LINEA_MAINNET_RPC_URL; - case 'LOCALHOST': + case CHAIN_IDS.LOCALHOST: return LOCALHOST_RPC_URL; default: // Default to MAINNET if no match is found @@ -371,12 +371,9 @@ export const getNetworkFees = async (notification: OnChainRawNotification) => { throw new Error('Invalid notification type'); } - // eslint-disable-next-line camelcase - const { chain_id } = notification; - const chainId = decimalToHex(chain_id); - + const chainId = decimalToHex(notification.chain_id); const provider = new JsonRpcProvider( - getRpcUrlByChainId(`0x${chainId}` as keyof typeof CHAIN_IDS), + getRpcUrlByChainId(`0x${chainId}` as HexChainId), ); if (!provider) {