diff --git a/ui/components/multichain/pages/permissions-page/permissions-page.js b/ui/components/multichain/pages/permissions-page/permissions-page.js index 8ddb8066f366..fdf44f99872e 100644 --- a/ui/components/multichain/pages/permissions-page/permissions-page.js +++ b/ui/components/multichain/pages/permissions-page/permissions-page.js @@ -2,6 +2,7 @@ import React, { useEffect, useRef, useState } from 'react'; import { useHistory } from 'react-router-dom'; import { useSelector } from 'react-redux'; import { isSnapId } from '@metamask/snaps-utils'; +import { SubjectType } from '@metamask/permission-controller'; import { Content, Header, Page } from '../page'; import { Box, @@ -27,8 +28,14 @@ import { REVIEW_PERMISSIONS, GATOR_PERMISSIONS, } from '../../../../helpers/constants/routes'; -import { getConnectedSitesListWithNetworkInfo } from '../../../../selectors'; +import { + getConnectedSitesListWithNetworkInfo, + getTargetSubjectMetadata, +} from '../../../../selectors'; +import { getGatorPermissionsMap } from '../../../../selectors/gator-permissions/gator-permissions'; import { isGatorPermissionsRevocationFeatureEnabled } from '../../../../../shared/modules/environment'; +import { getURLHostName } from '../../../../helpers/utils/util'; +import { getNetworkNameByChainId } from '../../../../../shared/modules/feature-flags'; import { ConnectionListItem } from './connection-list-item'; export const PermissionsPage = () => { @@ -39,10 +46,85 @@ export const PermissionsPage = () => { const sitesConnectionsList = useSelector( getConnectedSitesListWithNetworkInfo, ); + const gatorPermissionsMap = useSelector(getGatorPermissionsMap); + + // Get all unique site origins from gator permissions with their first chainId and all unique addresses + const getUniqueSiteOriginsFromGatorPermissions = (permissionsMap) => { + const siteOriginsMap = new Map(); + + Object.values(permissionsMap).forEach((permissionTypeMap) => { + Object.values(permissionTypeMap).forEach((permissions) => { + permissions.forEach((permission) => { + if (permission.siteOrigin) { + if (!siteOriginsMap.has(permission.siteOrigin)) { + // Store the first permission data for this site origin + siteOriginsMap.set(permission.siteOrigin, { + addresses: new Set(), + chainId: permission.permissionResponse.chainId, + }); + } + + // Add address to the set if it exists + const permissionData = siteOriginsMap.get(permission.siteOrigin); + if (permission.permissionResponse.address) { + permissionData.addresses.add( + permission.permissionResponse.address.toLowerCase(), + ); + } + } + }); + }); + }); + + // Convert Set to Array for each site origin + siteOriginsMap.forEach((permissionData) => { + permissionData.addresses = Array.from(permissionData.addresses); + }); + + return siteOriginsMap; + }; + + // Get merged connections list using useSelector to access getTargetSubjectMetadata + const mergedConnectionsList = useSelector((state) => { + if (!isGatorPermissionsRevocationFeatureEnabled()) { + return sitesConnectionsList; + } + + const gatorSiteOriginsMap = + getUniqueSiteOriginsFromGatorPermissions(gatorPermissionsMap); + const mergedConnections = { ...sitesConnectionsList }; + + // Add sites that only have gator permissions but no site connections + gatorSiteOriginsMap.forEach((permissionData, siteOrigin) => { + if (!mergedConnections[siteOrigin]) { + const { addresses, chainId } = permissionData; + const networkName = getNetworkNameByChainId(chainId); + + // Get subject metadata for name and iconUrl + const subjectMetadata = getTargetSubjectMetadata(state, siteOrigin); + const siteName = subjectMetadata?.name || getURLHostName(siteOrigin); + const siteIconUrl = subjectMetadata?.iconUrl || null; + + // Create a minimal connection object for sites that only have gator permissions + mergedConnections[siteOrigin] = { + addresses: addresses || [], + origin: siteOrigin, + name: siteName, + iconUrl: siteIconUrl, + subjectType: SubjectType.Website, + networkIconUrl: '', + networkName: networkName || '', + extensionId: null, + }; + } + }); + + return mergedConnections; + }); useEffect(() => { - setTotalConnections(Object.keys(sitesConnectionsList).length); - }, [sitesConnectionsList]); + setTotalConnections(Object.keys(mergedConnectionsList).length); + }, [mergedConnectionsList]); const handleConnectionClick = (connection) => { const hostName = connection.origin; @@ -100,7 +182,7 @@ export const PermissionsPage = () => { {totalConnections > 0 ? ( - renderConnectionsList(sitesConnectionsList) + renderConnectionsList(mergedConnectionsList) ) : (