diff --git a/app/scripts/controllers/permissions/specifications.js b/app/scripts/controllers/permissions/specifications.js index 2d25ab16b1e4..ea2392bfd7e4 100644 --- a/app/scripts/controllers/permissions/specifications.js +++ b/app/scripts/controllers/permissions/specifications.js @@ -212,6 +212,11 @@ export const getPermissionSpecifications = ({ subjectTypes: [SubjectType.Website], factory: (permissionOptions, requestData) => { + if (requestData === undefined) { + return constructPermission({ + ...permissionOptions, + }); + } if (!requestData.approvedChainIds) { throw new Error( `${PermissionNames.permittedChains}: No approved networks specified.`, diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index c510492dc0dd..5e624d4da0c7 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -3144,6 +3144,7 @@ export default class MetamaskController extends EventEmitter { getUseRequestQueue: this.preferencesController.getUseRequestQueue.bind( this.preferencesController, ), + grantPermissionsIncremental: this.permissionController.grantPermissionsIncremental.bind(this.permissionController), getProviderConfig: () => this.networkController.state.providerConfig, setSecurityAlertsEnabled: preferencesController.setSecurityAlertsEnabled.bind( diff --git a/ui/components/multichain/network-list-menu/network-list-menu.js b/ui/components/multichain/network-list-menu/network-list-menu.js index 3900ba4a067a..5dab1b89c357 100644 --- a/ui/components/multichain/network-list-menu/network-list-menu.js +++ b/ui/components/multichain/network-list-menu/network-list-menu.js @@ -15,6 +15,7 @@ import { updateNetworksList, setNetworkClientIdForDomain, setEditedNetwork, + grantPermittedChain, } from '../../../store/actions'; import { FEATURED_RPCS, @@ -34,6 +35,7 @@ import { getNetworkConfigurations, getEditedNetwork, getAllDomains, + getPermittedChainsByOrigin, } from '../../../selectors'; import ToggleButton from '../../ui/toggle-button'; import { @@ -101,7 +103,8 @@ export const NetworkListMenu = ({ onClose }) => { const useRequestQueue = useSelector(getUseRequestQueue); const networkConfigurations = useSelector(getNetworkConfigurations); const domains = useSelector(getAllDomains); - + const chains = useSelector(getPermittedChainsByOrigin); +console.log(chains, "hh") const dispatch = useDispatch(); const history = useHistory(); const trackEvent = useContext(MetaMetricsContext); @@ -171,6 +174,7 @@ export const NetworkListMenu = ({ onClose }) => { return sortedNonTestNetworks; }; + //check if not granted chain is clicked, then show the toast and grant permission const networksList = newOrderNetworks(); const [items, setItems] = useState([...networksList]); @@ -303,6 +307,7 @@ export const NetworkListMenu = ({ onClose }) => { onClick={() => { dispatch(toggleNetworkMenu()); dispatch(setActiveNetwork(network.providerType || network.id)); + grantPermittedChain(selectedTabOrigin, network.chainId); // If presently on and connected to a dapp, communicate a change to // the dapp via silent switchEthereumChain that the network has diff --git a/ui/selectors/permissions.js b/ui/selectors/permissions.js index 65f2acf37c4b..9f08979ee6e0 100644 --- a/ui/selectors/permissions.js +++ b/ui/selectors/permissions.js @@ -83,6 +83,7 @@ export function getPermittedAccountsForSelectedTab(state, activeTab) { */ export function getPermittedAccountsByOrigin(state) { const subjects = getPermissionSubjects(state); + console.log(subjects, "nidhi") return Object.keys(subjects).reduce((acc, subjectKey) => { const accounts = getAccountsFromSubject(subjects[subjectKey]); if (accounts.length > 0) { @@ -92,6 +93,18 @@ export function getPermittedAccountsByOrigin(state) { }, {}); } +export function getPermittedChainsByOrigin(state) { + const subjects = getPermissionSubjects(state); + console.log(subjects, 'nidhi'); + return Object.keys(subjects).reduce((acc, subjectKey) => { + const chains = getChainsFromSubject(subjects[subjectKey]); + if (chains.length > 0) { + acc[subjectKey] = chains; + } + return acc; + }, {}); +} + export function getSubjectMetadata(state) { return state.metamask.subjectMetadata; } @@ -256,6 +269,14 @@ function getAccountsPermissionFromSubject(subject = {}) { return subject.permissions?.eth_accounts || {}; } +function getChainsFromSubject(subject) { + return getChainsFromPermission(getChainsPermissionFromSubject(subject)); +} + +function getChainsPermissionFromSubject(subject = {}) { + return subject.permissions?.['endowment:permitted-chains'] || {}; +} + function getAccountsFromPermission(accountsPermission) { const accountsCaveat = getAccountsCaveatFromPermission(accountsPermission); return accountsCaveat && Array.isArray(accountsCaveat.value) @@ -263,6 +284,22 @@ function getAccountsFromPermission(accountsPermission) { : []; } +function getChainsFromPermission(chainsPermission) { + const chainsCaveat = getChainsCaveatFromPermission(chainsPermission); + return chainsCaveat && Array.isArray(chainsCaveat.value) + ? chainsCaveat.value + : []; +} + +function getChainsCaveatFromPermission(chainsPermission = {}) { + return ( + Array.isArray(chainsPermission.caveats) && + chainsPermission.caveats.find( + (caveat) => caveat.type === CaveatTypes.restrictNetworkSwitching, + ) + ); +} + function getAccountsCaveatFromPermission(accountsPermission = {}) { return ( Array.isArray(accountsPermission.caveats) && diff --git a/ui/store/actions.ts b/ui/store/actions.ts index ddc98bf988d7..5845677e9638 100644 --- a/ui/store/actions.ts +++ b/ui/store/actions.ts @@ -130,6 +130,8 @@ import { MetaMaskReduxState, TemporaryMessageDataType, } from './store'; +import { CaveatFactories, PermissionNames } from '../../app/scripts/controllers/permissions/specifications'; +import { CaveatTypes } from '../../shared/constants/permissions'; type CustomGasSettings = { gas?: string; @@ -5580,6 +5582,26 @@ export async function getNextAvailableAccountName( ); } +export async function grantPermittedChain( + selectedTabOrigin: string, + chainId?: [], +): Promise { + return await submitRequestToBackground('grantPermissionsIncremental', [ + { + subject: { origin: selectedTabOrigin }, + approvedPermissions: { + [PermissionNames.permittedChains]: { + caveats: [ + CaveatFactories[CaveatTypes.restrictNetworkSwitching]( + [chainId], + ), + ], + }, + }, + } + ]); +} + export async function decodeTransactionData({ transactionData, contractAddress,