mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 01:47:00 +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:
parent
05ab94fd1c
commit
f162c58f5a
22
app/_locales/en/messages.json
generated
22
app/_locales/en/messages.json
generated
@ -207,6 +207,28 @@
|
||||
"addEthereumChainConfirmationTitle": {
|
||||
"message": "Allow this site to add a network?"
|
||||
},
|
||||
"addEthereumChainWarningModalHeader": {
|
||||
"message": "Only add this RPC provider if you’re 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"
|
||||
},
|
||||
|
@ -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
|
||||
|
@ -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';
|
||||
|
@ -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';
|
@ -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;
|
1
ui/components/app/confirmation-warning-modal/index.js
Normal file
1
ui/components/app/confirmation-warning-modal/index.js
Normal file
@ -0,0 +1 @@
|
||||
export { default } from './confirmation-warning-modal';
|
28
ui/components/app/confirmation-warning-modal/index.scss
Normal file
28
ui/components/app/confirmation-warning-modal/index.scss
Normal 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;
|
||||
}
|
||||
}
|
@ -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={
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user