From 60ec8229171d63410490c5a01aeec9db67dca003 Mon Sep 17 00:00:00 2001 From: EtherWizard33 <165834542+EtherWizard33@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:02:05 -0500 Subject: [PATCH] feat: non-permissioned networks, when a dapp finds itself on a global network for which it doesn't have a granted network permission (#12212) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit non-permissioned networks, when a dapp finds itself on a global network for which it doesn't have a granted network permission ## **Description** Figma: https://www.figma.com/design/njDnVDROVuIwLbjUjkUYuO/MC-Mobile-Amon-Hen?node-id=3109-157108&node-type=canvas&m=dev ## **Related issues** Contributes to: https://github.com/MetaMask/MetaMask-planning/issues/3598 ## **Manual testing steps** 1. Start with a global network and a dapp connected to it 2. From the home screen, switch the network 3. Go back to the dapp, the bottom sheet will come up. This works also with multiple dapps open at once, the bottom sheet comes up the next time the dapp is in focus. ## **Screenshots/Recordings** | Before (switch to non permitted change was not handled) | After (handled) | |--------------|--------------| | Screenshot 2024-04-18 at 3 56 43 PM |Screenshot 2024-04-18s at 3 56 43 PM | ## **Pre-merge author checklist** - [ ] 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). - [ ] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] 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. --- app/components/Nav/App/index.js | 5 + .../NetworkSelectorList.styles.ts | 4 - .../NetworkSelectorList.tsx | 2 - .../PermissionsSummary.styles.ts | 15 +- .../PermissionsSummary/PermissionsSummary.tsx | 92 ++++++-- .../PermissionsSummary.types.ts | 3 + .../PermissionsSummary.test.tsx.snap | 36 ++- .../AccountPermissions/AccountPermissions.tsx | 178 +++++++++++++- .../AccountPermissions.types.ts | 2 + .../ConnectionDetails/ConnectionDetails.tsx | 4 +- .../NetworkPermissionsConnected.styles.ts | 50 ++++ .../NetworkPermissionsConnected.tsx | 220 ++++++++++++++++++ .../NetworkPermissionsConnected.types.ts | 24 ++ .../NetworkPermissionsConnected/index.ts | 2 + .../PermittedNetworksInfoSheet.styles.ts | 26 +++ .../PermittedNetworksInfoSheet.tsx | 57 +++++ .../PermittedNetworksInfoSheet/index.ts | 1 + app/components/Views/Browser/index.js | 23 +- app/components/Views/BrowserTab/index.js | 73 ++++++ .../NetworkConnectMultiSelector.styles.ts | 3 +- .../NetworkConnectMultiSelector.tsx | 46 +++- .../NetworkConnectMultiSelector.types.ts | 1 + app/constants/navigation/Routes.ts | 1 + .../RPCMethods/lib/ethereum-chain-utils.js | 9 +- .../wallet_addEthereumChain.test.js | 10 +- .../wallet_switchEthereumChain.test.js | 4 +- app/util/networks/index.js | 9 +- bitrise.yml | 3 + locales/languages/en.json | 10 +- sonar-project.properties | 2 +- 30 files changed, 847 insertions(+), 68 deletions(-) create mode 100644 app/components/Views/AccountPermissions/NetworkPermissionsConnected/NetworkPermissionsConnected.styles.ts create mode 100644 app/components/Views/AccountPermissions/NetworkPermissionsConnected/NetworkPermissionsConnected.tsx create mode 100644 app/components/Views/AccountPermissions/NetworkPermissionsConnected/NetworkPermissionsConnected.types.ts create mode 100644 app/components/Views/AccountPermissions/NetworkPermissionsConnected/index.ts create mode 100644 app/components/Views/AccountPermissions/PermittedNetworksInfoSheet/PermittedNetworksInfoSheet.styles.ts create mode 100644 app/components/Views/AccountPermissions/PermittedNetworksInfoSheet/PermittedNetworksInfoSheet.tsx create mode 100644 app/components/Views/AccountPermissions/PermittedNetworksInfoSheet/index.ts diff --git a/app/components/Nav/App/index.js b/app/components/Nav/App/index.js index 0ad4fa844e6..8763bf589d3 100644 --- a/app/components/Nav/App/index.js +++ b/app/components/Nav/App/index.js @@ -118,6 +118,7 @@ import OnboardingAssetsSettings from '../../Views/OnboardingSuccess/OnboardingAs import OnboardingSecuritySettings from '../../Views/OnboardingSuccess/OnboardingSecuritySettings'; import BasicFunctionalityModal from '../../UI/BasicFunctionality/BasicFunctionalityModal/BasicFunctionalityModal'; import ProfileSyncingModal from '../../UI/ProfileSyncing/ProfileSyncingModal/ProfileSyncingModal'; +import PermittedNetworksInfoSheet from '../../Views/AccountPermissions/PermittedNetworksInfoSheet/PermittedNetworksInfoSheet'; import ResetNotificationsModal from '../../UI/Notification/ResetNotificationsModal'; import NFTAutoDetectionModal from '../../../../app/components/Views/NFTAutoDetectionModal/NFTAutoDetectionModal'; import NftOptions from '../../../components/Views/NftOptions'; @@ -430,6 +431,10 @@ const RootModalFlow = () => ( name={Routes.SHEET.CONNECTION_DETAILS} component={ConnectionDetails} /> + StyleSheet.create({ - networkItemContainer: { - paddingHorizontal: 10, - paddingVertical: 14, - }, networkAvatar: { marginHorizontal: 10, }, diff --git a/app/components/UI/NetworkSelectorList/NetworkSelectorList.tsx b/app/components/UI/NetworkSelectorList/NetworkSelectorList.tsx index 152348b8573..551146856e0 100644 --- a/app/components/UI/NetworkSelectorList/NetworkSelectorList.tsx +++ b/app/components/UI/NetworkSelectorList/NetworkSelectorList.tsx @@ -67,7 +67,6 @@ const NetworkSelectorList = ({ size: AvatarSize.Sm, }} disabled={isDisabled} - style={styles.networkItemContainer} > {renderRightAccessory?.(id, name)} @@ -79,7 +78,6 @@ const NetworkSelectorList = ({ renderRightAccessory, isSelectionDisabled, onSelectNetwork, - styles, isMultiSelect, ], ); diff --git a/app/components/UI/PermissionsSummary/PermissionsSummary.styles.ts b/app/components/UI/PermissionsSummary/PermissionsSummary.styles.ts index 3c25f4830a7..26b3b380eec 100644 --- a/app/components/UI/PermissionsSummary/PermissionsSummary.styles.ts +++ b/app/components/UI/PermissionsSummary/PermissionsSummary.styles.ts @@ -31,12 +31,13 @@ const createStyles = (params: { marginLeft: 24, }, bottomButtonsContainer: { - marginTop: 16, + marginTop: 8, }, actionButtonsContainer: { flex: 0, flexDirection: 'row', paddingHorizontal: 24, + marginTop: 8, }, buttonPositioning: { flex: 1, @@ -59,6 +60,9 @@ const createStyles = (params: { justifyContent: 'center', alignItems: 'center', }, + logoContainerNonDapp: { + marginTop: 8, + }, domainLogoContainer: { width: 32, height: 32, @@ -81,6 +85,7 @@ const createStyles = (params: { maxWidth: '75%', }, permissionRequestNetworkName: { + marginRight: 4, maxWidth: '75%', }, avatarGroup: { @@ -122,6 +127,7 @@ const createStyles = (params: { dataIcon: { alignSelf: 'flex-start' }, disconnectAllContainer: { marginHorizontal: 24, + marginTop: 8, flexDirection: 'row', }, disconnectButton: { flex: 1 }, @@ -129,6 +135,13 @@ const createStyles = (params: { width: 56, alignItems: 'center', }, + nonDappNetworkSwitchButtons: { + gap: 16, + }, + description: { + marginHorizontal: 24, + marginBottom: 16, + }, }); }; diff --git a/app/components/UI/PermissionsSummary/PermissionsSummary.tsx b/app/components/UI/PermissionsSummary/PermissionsSummary.tsx index f48936e74ef..1d31aec69d9 100644 --- a/app/components/UI/PermissionsSummary/PermissionsSummary.tsx +++ b/app/components/UI/PermissionsSummary/PermissionsSummary.tsx @@ -1,4 +1,4 @@ -import React, { useCallback } from 'react'; +import React, { useCallback, useMemo } from 'react'; import StyledButton from '../StyledButton'; import { ImageSourcePropType, @@ -42,6 +42,9 @@ import ButtonIcon, { import { getNetworkImageSource } from '../../../util/networks'; import Engine from '../../../core/Engine'; import { SDKSelectorsIDs } from '../../../../e2e/selectors/Settings/SDK.selectors'; +import { useSelector } from 'react-redux'; +import { selectProviderConfig } from '../../../selectors/networkController'; +import { useNetworkInfo } from '../../../selectors/selectedNetworkController'; const PermissionsSummary = ({ currentPageInformation, @@ -57,16 +60,24 @@ const PermissionsSummary = ({ isRenderedAsBottomSheet = true, isDisconnectAllShown = true, isNetworkSwitch = false, + isNonDappNetworkSwitch = false, accountAddresses = [], accounts = [], networkAvatars = [], + onAddNetwork = () => undefined, + onChooseFromPermittedNetworks = () => undefined, }: PermissionsSummaryProps) => { const { colors } = useTheme(); const { styles } = useStyles(styleSheet, { isRenderedAsBottomSheet }); const { navigate } = useNavigation(); const selectedAccount = useSelectedAccount(); + const providerConfig = useSelector(selectProviderConfig); - const hostname = new URL(currentPageInformation.url).hostname; + const hostname = useMemo( + () => new URL(currentPageInformation.url).hostname, + [currentPageInformation.url], + ); + const networkInfo = useNetworkInfo(hostname); // if network switch, we get the chain name from the customNetworkInformation let chainName = ''; @@ -117,7 +128,7 @@ const PermissionsSummary = ({ return ( - {onBack && ( + {onBack && !isNonDappNetworkSwitch && ( - {renderTopIcon()} + + {renderTopIcon()} + {!isRenderedAsBottomSheet && ( - {isNetworkSwitch && ( + {(isNetworkSwitch || isNonDappNetworkSwitch) && ( <> @@ -329,19 +347,32 @@ const PermissionsSummary = ({ {strings('permissions.requesting_for')} - {chainName} + {isNonDappNetworkSwitch + ? networkInfo?.networkName || providerConfig.nickname + : chainName} )} - {!isNetworkSwitch && ( + {!isNetworkSwitch && !isNonDappNetworkSwitch && ( <> @@ -363,7 +394,7 @@ const PermissionsSummary = ({ )} - {!isNetworkSwitch && renderEndAccessory()} + {!isNetworkSwitch && !isNonDappNetworkSwitch && renderEndAccessory()} ); @@ -376,7 +407,9 @@ const PermissionsSummary = ({ {renderHeader()} - {!isAlreadyConnected || isNetworkSwitch + {isNonDappNetworkSwitch + ? strings('permissions.title_add_network_permission') + : !isAlreadyConnected || isNetworkSwitch ? strings('permissions.title_dapp_url_wants_to', { dappUrl: hostname, }) @@ -385,7 +418,14 @@ const PermissionsSummary = ({ })} - {/*TODO These should be conditional upon which permissions are being requested*/} + {isNonDappNetworkSwitch && ( + + {strings('permissions.non_permitted_network_description')} + + )} {!isNetworkSwitch && renderAccountPermissionsRequestInfoCard()} {renderNetworkPermissionsRequestInfoCard()} @@ -405,7 +445,7 @@ const PermissionsSummary = ({ /> )} - {showActionButtons && ( + {showActionButtons && !isNonDappNetworkSwitch && ( )} + {isNonDappNetworkSwitch && ( + + +