1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-22 17:33:23 +01:00

Allow adding networks with the same chainId as a preloaded/default network via wallet_AddEthereumChain API (#16733)

* allow adding networks with the same chainId as an existing network via API

Co-authored-by: Kurush Dubash <kurush@alchemyapi.io>
This commit is contained in:
Alex Donesky 2022-12-02 21:14:27 -06:00 committed by GitHub
parent 05ab94fd1c
commit f162c58f5a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 222 additions and 15 deletions

View File

@ -207,6 +207,28 @@
"addEthereumChainConfirmationTitle": {
"message": "Allow this site to add a network?"
},
"addEthereumChainWarningModalHeader": {
"message": "Only add this RPC provider if youre sure you can trust it. $1",
"description": "$1 is addEthereumChainWarningModalHeaderPartTwo passed separately so that it can be bolded"
},
"addEthereumChainWarningModalHeaderPartTwo": {
"message": "Malicious providers may lie about the state of the blockchain and record your network activity."
},
"addEthereumChainWarningModalListHeader": {
"message": "It's important that your provider is reliable, as it has the power to:"
},
"addEthereumChainWarningModalListPointOne": {
"message": "See your accounts and IP address, and associate them together"
},
"addEthereumChainWarningModalListPointThree": {
"message": "Show account balances and other on-chain states"
},
"addEthereumChainWarningModalListPointTwo": {
"message": "Broadcast your transactions"
},
"addEthereumChainWarningModalTitle": {
"message": "You are adding a new RPC provider for Ethereum Mainnet"
},
"addFriendsAndAddresses": {
"message": "Add friends and addresses you trust"
},

View File

@ -11,7 +11,6 @@ import {
isSafeChainId,
} from '../../../../../shared/modules/network.utils';
import { jsonRpcRequest } from '../../../../../shared/modules/rpc.utils';
import { CHAIN_ID_TO_NETWORK_ID_MAP } from '../../../../../shared/constants/network';
const addEthereumChain = {
methodNames: [MESSAGE_TYPE.ADD_ETHEREUM_CHAIN],
@ -140,14 +139,6 @@ async function addEthereumChainHandler(
);
}
if (CHAIN_ID_TO_NETWORK_ID_MAP[_chainId]) {
return end(
ethErrors.rpc.invalidParams({
message: `May not specify default MetaMask chain.`,
}),
);
}
const existingNetwork = findCustomRpcBy({ chainId: _chainId });
// if the request is to add a network that is already added and configured

View File

@ -12,6 +12,7 @@
@import 'beta-header/index';
@import 'cancel-speedup-popover/index';
@import 'confirm-page-container/index';
@import 'confirmation-warning-modal/index';
@import 'confirm-page-container/enableEIP1559V2-notice';
@import 'collectibles-items/index';
@import 'collectibles-tab/index';

View File

@ -0,0 +1,11 @@
import React from 'react';
import ConfirmationWarningModal from '.';
export default {
title: 'Components/App/ConfirmationWarningModal',
id: __filename,
};
export const DefaultStory = (args) => <ConfirmationWarningModal {...args} />;
DefaultStory.storyName = 'Default';

View File

@ -0,0 +1,105 @@
import React from 'react';
import PropTypes from 'prop-types';
import { useI18nContext } from '../../../hooks/useI18nContext';
import Popover from '../../ui/popover';
import Box from '../../ui/box';
import Button from '../../ui/button';
import Typography from '../../ui/typography';
import {
DISPLAY,
FLEX_DIRECTION,
FONT_WEIGHT,
JUSTIFY_CONTENT,
TYPOGRAPHY,
ALIGN_ITEMS,
} from '../../../helpers/constants/design-system';
const ConfirmationWarningModal = ({ onSubmit, onCancel }) => {
const t = useI18nContext();
return (
<Popover
className="confirmation-warning-modal__content"
footer={
<Box
display={DISPLAY.FLEX}
flexDirection={FLEX_DIRECTION.COLUMN}
justifyContent={JUSTIFY_CONTENT.SPACE_BETWEEN}
className="confirmation-warning-modal__footer"
>
<Button
className="confirmation-warning-modal__footer__approve-button"
type="danger-primary"
onClick={onSubmit}
>
{t('approveButtonText')}
</Button>
<Button
className="confirmation-warning-modal__footer__cancel-button"
type="secondary"
onClick={onCancel}
>
{t('reject')}
</Button>
</Box>
}
>
<Box
display={DISPLAY.FLEX}
flexDirection={FLEX_DIRECTION.ROW}
alignItems={ALIGN_ITEMS.CENTER}
padding={3}
margin={0}
className="confirmation-warning-modal__content__header"
>
<i className="fa fa-exclamation-triangle confirmation-warning-modal__content__header__warning-icon" />
<Typography variant={TYPOGRAPHY.H4} fontWeight={FONT_WEIGHT.BOLD}>
{t('addEthereumChainWarningModalTitle')}
</Typography>
</Box>
<Box marginLeft={6} marginRight={6} marginTop={0} marginBottom={3}>
<Typography marginTop={4} variant={TYPOGRAPHY.H6}>
{t('addEthereumChainWarningModalHeader', [
<strong key="part-2">
{t('addEthereumChainWarningModalHeaderPartTwo')}
</strong>,
])}
</Typography>
<Typography marginTop={4} variant={TYPOGRAPHY.H6}>
{t('addEthereumChainWarningModalListHeader')}
</Typography>
<ul>
<li>
<Typography marginTop={2} variant={TYPOGRAPHY.H6}>
{t('addEthereumChainWarningModalListPointOne')}
</Typography>
</li>
<li>
<Typography marginTop={2} variant={TYPOGRAPHY.H6}>
{t('addEthereumChainWarningModalListPointTwo')}
</Typography>
</li>
<li>
<Typography marginTop={2} variant={TYPOGRAPHY.H6}>
{t('addEthereumChainWarningModalListPointThree')}
</Typography>
</li>
</ul>
</Box>
</Popover>
);
};
ConfirmationWarningModal.propTypes = {
/**
* Function that approves collection
*/
onSubmit: PropTypes.func,
/**
* Function that rejects collection
*/
onCancel: PropTypes.func,
};
export default ConfirmationWarningModal;

View File

@ -0,0 +1 @@
export { default } from './confirmation-warning-modal';

View File

@ -0,0 +1,28 @@
.confirmation-warning-modal {
&__content {
ul {
padding-inline-start: 1rem;
margin-block-start: 0;
list-style: disc outside;
}
li {
display: list-item;
}
&__header {
border-bottom: 1px solid var(--color-border-muted);
&__warning-icon {
padding-top: 7px;
margin-right: 10px;
color: var(--color-error-default);
}
}
}
&__footer {
width: 100%;
height: 100px;
}
}

View File

@ -14,6 +14,7 @@ import { produce } from 'immer';
import { MESSAGE_TYPE } from '../../../shared/constants/app';
import Box from '../../components/ui/box';
import MetaMaskTemplateRenderer from '../../components/app/metamask-template-renderer';
import ConfirmationWarningModal from '../../components/app/confirmation-warning-modal';
import { DEFAULT_ROUTE } from '../../helpers/constants/routes';
import {
COLORS,
@ -32,7 +33,11 @@ import NetworkDisplay from '../../components/app/network-display/network-display
import Callout from '../../components/ui/callout';
import SiteOrigin from '../../components/ui/site-origin';
import ConfirmationFooter from './components/confirmation-footer';
import { getTemplateValues, getTemplateAlerts } from './templates';
import {
getTemplateValues,
getTemplateAlerts,
getTemplateState,
} from './templates';
// TODO(rekmarks): This component and all of its sub-components should probably
// be renamed to "Dialog", now that we are using it in that manner.
@ -125,6 +130,28 @@ function useAlertState(pendingConfirmation) {
return [alertState, dismissAlert];
}
function useTemplateState(pendingConfirmation) {
const [templateState, setTemplateState] = useState({});
useEffect(() => {
let isMounted = true;
if (pendingConfirmation) {
getTemplateState(pendingConfirmation).then((state) => {
if (isMounted && Object.values(state).length > 0) {
setTemplateState((prevState) => ({
...prevState,
[pendingConfirmation.id]: state,
}));
}
});
}
return () => {
isMounted = false;
};
}, [pendingConfirmation]);
return [templateState];
}
export default function ConfirmationPage({
redirectToHomeOnZeroConfirmations = true,
}) {
@ -140,6 +167,8 @@ export default function ConfirmationPage({
const pendingConfirmation = pendingConfirmations[currentPendingConfirmation];
const originMetadata = useOriginMetadata(pendingConfirmation?.origin) || {};
const [alertState, dismissAlert] = useAlertState(pendingConfirmation);
const [templateState] = useTemplateState(pendingConfirmation);
const [showWarningModal, setShowWarningModal] = useState(false);
const [inputStates, setInputStates] = useState({});
const setInputState = (key, value) => {
@ -200,11 +229,13 @@ export default function ConfirmationPage({
};
const handleSubmit = () =>
templatedValues.onSubmit(
hasInputState(pendingConfirmation.type)
? inputStates[MESSAGE_TYPE.SNAP_DIALOG_PROMPT]
: null,
);
templateState[pendingConfirmation.id]?.useWarningModal
? setShowWarningModal(true)
: templatedValues.onSubmit(
hasInputState(pendingConfirmation.type)
? inputStates[MESSAGE_TYPE.SNAP_DIALOG_PROMPT]
: null,
);
useEffect(() => {
// If the number of pending confirmations reduces to zero when the user
@ -291,6 +322,15 @@ export default function ConfirmationPage({
</Box>
)}
<MetaMaskTemplateRenderer sections={templatedValues.content} />
{showWarningModal && (
<ConfirmationWarningModal
onSubmit={async () => {
await templatedValues.onSubmit();
setShowWarningModal(false);
}}
onCancel={templatedValues.onCancel}
/>
)}
</div>
<ConfirmationFooter
alerts={

View File

@ -145,6 +145,13 @@ async function getAlerts(pendingApproval) {
return alerts;
}
function getState(pendingApproval) {
if (parseInt(pendingApproval.requestData.chainId, 16) === 1) {
return { useWarningModal: true };
}
return {};
}
function getValues(pendingApproval, t, actions, history) {
const originIsMetaMask = pendingApproval.origin === 'metamask';
@ -346,6 +353,7 @@ function getValues(pendingApproval, t, actions, history) {
const addEthereumChain = {
getAlerts,
getValues,
getState,
};
export default addEthereumChain;