mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 09:57:02 +01:00
Fix 'block link explorer on custom networks' (#13870)
* Created a logic for the 'Add a block explorer URL' Removed unused message Message logic rollback Modified history push operation WIP: Pushing before rebasing Applied requested changes Removed unintenionally added code * Lint fix * Metrics fixed
This commit is contained in:
parent
3e7d4d314c
commit
ea247d4e4a
3
app/_locales/en/messages.json
generated
3
app/_locales/en/messages.json
generated
@ -121,6 +121,9 @@
|
||||
"addAlias": {
|
||||
"message": "Add alias"
|
||||
},
|
||||
"addBlockExplorer": {
|
||||
"message": "Add a block explorer"
|
||||
},
|
||||
"addContact": {
|
||||
"message": "Add contact"
|
||||
},
|
||||
|
@ -5,10 +5,14 @@ import { useDispatch, useSelector } from 'react-redux';
|
||||
import { getAccountLink } from '@metamask/etherscan-link';
|
||||
|
||||
import { showModal } from '../../../store/actions';
|
||||
import { CONNECTED_ROUTE } from '../../../helpers/constants/routes';
|
||||
import {
|
||||
CONNECTED_ROUTE,
|
||||
NETWORKS_ROUTE,
|
||||
} from '../../../helpers/constants/routes';
|
||||
import { getURLHostName } from '../../../helpers/utils/util';
|
||||
import { Menu, MenuItem } from '../../ui/menu';
|
||||
import {
|
||||
getBlockExplorerLinkText,
|
||||
getCurrentChainId,
|
||||
getCurrentKeyring,
|
||||
getRpcPrefsForCurrentProvider,
|
||||
@ -34,9 +38,30 @@ export default function AccountOptionsMenu({ anchorElement, onClose }) {
|
||||
const { blockExplorerUrl } = rpcPrefs;
|
||||
const blockExplorerUrlSubTitle = getURLHostName(blockExplorerUrl);
|
||||
const trackEvent = useContext(MetaMetricsContext);
|
||||
const blockExplorerLinkText = useSelector(getBlockExplorerLinkText);
|
||||
|
||||
const isRemovable = keyring.type !== 'HD Key Tree';
|
||||
|
||||
const routeToAddBlockExplorerUrl = () => {
|
||||
history.push(`${NETWORKS_ROUTE}#blockExplorerUrl`);
|
||||
};
|
||||
|
||||
const openBlockExplorer = () => {
|
||||
trackEvent({
|
||||
event: 'Clicked Block Explorer Link',
|
||||
category: EVENT.CATEGORIES.NAVIGATION,
|
||||
properties: {
|
||||
link_type: 'Account Tracker',
|
||||
action: 'Account Options',
|
||||
block_explorer_domain: getURLHostName(addressLink),
|
||||
},
|
||||
});
|
||||
global.platform.openTab({
|
||||
url: addressLink,
|
||||
});
|
||||
onClose();
|
||||
};
|
||||
|
||||
return (
|
||||
<Menu
|
||||
anchorElement={anchorElement}
|
||||
@ -44,21 +69,11 @@ export default function AccountOptionsMenu({ anchorElement, onClose }) {
|
||||
onHide={onClose}
|
||||
>
|
||||
<MenuItem
|
||||
onClick={() => {
|
||||
trackEvent({
|
||||
event: 'Clicked Block Explorer Link',
|
||||
category: EVENT.CATEGORIES.NAVIGATION,
|
||||
properties: {
|
||||
link_type: 'Account Tracker',
|
||||
action: 'Account Options',
|
||||
block_explorer_domain: getURLHostName(addressLink),
|
||||
},
|
||||
});
|
||||
global.platform.openTab({
|
||||
url: addressLink,
|
||||
});
|
||||
onClose();
|
||||
}}
|
||||
onClick={
|
||||
blockExplorerLinkText.firstPart === 'addBlockExplorer'
|
||||
? routeToAddBlockExplorerUrl
|
||||
: openBlockExplorer
|
||||
}
|
||||
subtitle={
|
||||
blockExplorerUrlSubTitle ? (
|
||||
<span className="account-options-menu__explorer-origin">
|
||||
@ -68,9 +83,12 @@ export default function AccountOptionsMenu({ anchorElement, onClose }) {
|
||||
}
|
||||
iconClassName="fas fa-external-link-alt"
|
||||
>
|
||||
{rpcPrefs.blockExplorerUrl
|
||||
? t('viewinExplorer', [t('blockExplorerAccountAction')])
|
||||
: t('viewOnEtherscan', [t('blockExplorerAccountAction')])}
|
||||
{t(
|
||||
blockExplorerLinkText.firstPart,
|
||||
blockExplorerLinkText.secondPart === ''
|
||||
? null
|
||||
: [t(blockExplorerLinkText.secondPart)],
|
||||
)}
|
||||
</MenuItem>
|
||||
{getEnvironmentType() === ENVIRONMENT_TYPE_FULLSCREEN ? null : (
|
||||
<MenuItem
|
||||
|
@ -9,6 +9,7 @@ import Button from '../../../ui/button';
|
||||
import { getURLHostName } from '../../../../helpers/utils/util';
|
||||
import { isHardwareKeyring } from '../../../../helpers/utils/hardware';
|
||||
import { EVENT } from '../../../../../shared/constants/metametrics';
|
||||
import { NETWORKS_ROUTE } from '../../../../helpers/constants/routes';
|
||||
|
||||
export default class AccountDetailsModal extends Component {
|
||||
static propTypes = {
|
||||
@ -19,6 +20,9 @@ export default class AccountDetailsModal extends Component {
|
||||
keyrings: PropTypes.array,
|
||||
rpcPrefs: PropTypes.object,
|
||||
accounts: PropTypes.array,
|
||||
history: PropTypes.object,
|
||||
hideModal: PropTypes.func,
|
||||
blockExplorerLinkText: PropTypes.object,
|
||||
};
|
||||
|
||||
static contextTypes = {
|
||||
@ -35,6 +39,9 @@ export default class AccountDetailsModal extends Component {
|
||||
keyrings,
|
||||
rpcPrefs,
|
||||
accounts,
|
||||
history,
|
||||
hideModal,
|
||||
blockExplorerLinkText,
|
||||
} = this.props;
|
||||
const { name, address } = selectedIdentity;
|
||||
|
||||
@ -54,6 +61,27 @@ export default class AccountDetailsModal extends Component {
|
||||
exportPrivateKeyFeatureEnabled = false;
|
||||
}
|
||||
|
||||
const routeToAddBlockExplorerUrl = () => {
|
||||
hideModal();
|
||||
history.push(`${NETWORKS_ROUTE}#blockExplorerUrl`);
|
||||
};
|
||||
|
||||
const openBlockExplorer = () => {
|
||||
const accountLink = getAccountLink(address, chainId, rpcPrefs);
|
||||
this.context.trackEvent({
|
||||
category: EVENT.CATEGORIES.NAVIGATION,
|
||||
event: 'Clicked Block Explorer Link',
|
||||
properties: {
|
||||
link_type: 'Account Tracker',
|
||||
action: 'Account Details Modal',
|
||||
block_explorer_domain: getURLHostName(accountLink),
|
||||
},
|
||||
});
|
||||
global.platform.openTab({
|
||||
url: accountLink,
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<AccountModalContainer className="account-details-modal">
|
||||
<EditableLabel
|
||||
@ -74,27 +102,18 @@ export default class AccountDetailsModal extends Component {
|
||||
<Button
|
||||
type="secondary"
|
||||
className="account-details-modal__button"
|
||||
onClick={() => {
|
||||
const accountLink = getAccountLink(address, chainId, rpcPrefs);
|
||||
this.context.trackEvent({
|
||||
category: EVENT.CATEGORIES.NAVIGATION,
|
||||
event: 'Clicked Block Explorer Link',
|
||||
properties: {
|
||||
link_type: 'Account Tracker',
|
||||
action: 'Account Details Modal',
|
||||
block_explorer_domain: getURLHostName(accountLink),
|
||||
},
|
||||
});
|
||||
global.platform.openTab({
|
||||
url: accountLink,
|
||||
});
|
||||
}}
|
||||
onClick={
|
||||
blockExplorerLinkText.firstPart === 'addBlockExplorer'
|
||||
? routeToAddBlockExplorerUrl
|
||||
: openBlockExplorer
|
||||
}
|
||||
>
|
||||
{rpcPrefs.blockExplorerUrl
|
||||
? this.context.t('blockExplorerView', [
|
||||
getURLHostName(rpcPrefs.blockExplorerUrl),
|
||||
])
|
||||
: this.context.t('etherscanViewOn')}
|
||||
{this.context.t(
|
||||
blockExplorerLinkText.firstPart,
|
||||
blockExplorerLinkText.secondPart === ''
|
||||
? null
|
||||
: [blockExplorerLinkText.secondPart],
|
||||
)}
|
||||
</Button>
|
||||
|
||||
{exportPrivateKeyFeatureEnabled ? (
|
||||
|
@ -1,10 +1,17 @@
|
||||
import { connect } from 'react-redux';
|
||||
import { showModal, setAccountLabel } from '../../../../store/actions';
|
||||
import { compose } from 'redux';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
import {
|
||||
showModal,
|
||||
setAccountLabel,
|
||||
hideModal,
|
||||
} from '../../../../store/actions';
|
||||
import {
|
||||
getSelectedIdentity,
|
||||
getRpcPrefsForCurrentProvider,
|
||||
getCurrentChainId,
|
||||
getMetaMaskAccountsOrdered,
|
||||
getBlockExplorerLinkText,
|
||||
} from '../../../../selectors';
|
||||
import AccountDetailsModal from './account-details-modal.component';
|
||||
|
||||
@ -15,6 +22,7 @@ const mapStateToProps = (state) => {
|
||||
keyrings: state.metamask.keyrings,
|
||||
rpcPrefs: getRpcPrefsForCurrentProvider(state),
|
||||
accounts: getMetaMaskAccountsOrdered(state),
|
||||
blockExplorerLinkText: getBlockExplorerLinkText(state, true),
|
||||
};
|
||||
};
|
||||
|
||||
@ -24,10 +32,13 @@ const mapDispatchToProps = (dispatch) => {
|
||||
dispatch(showModal({ name: 'EXPORT_PRIVATE_KEY' })),
|
||||
setAccountLabel: (address, label) =>
|
||||
dispatch(setAccountLabel(address, label)),
|
||||
hideModal: () => {
|
||||
dispatch(hideModal());
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps,
|
||||
export default compose(
|
||||
withRouter,
|
||||
connect(mapStateToProps, mapDispatchToProps),
|
||||
)(AccountDetailsModal);
|
||||
|
@ -30,14 +30,16 @@ describe('Account Details Modal', () => {
|
||||
name: 'Account 1',
|
||||
},
|
||||
},
|
||||
accounts: [
|
||||
{
|
||||
address: '0xAddress',
|
||||
lastSelected: 1637764711510,
|
||||
name: 'Account 1',
|
||||
balance: '0x543a5fb6caccf599',
|
||||
},
|
||||
],
|
||||
accounts: {
|
||||
address: '0xAddress',
|
||||
lastSelected: 1637764711510,
|
||||
name: 'Account 1',
|
||||
balance: '0x543a5fb6caccf599',
|
||||
},
|
||||
blockExplorerLinkText: {
|
||||
firstPart: 'addBlockExplorer',
|
||||
secondPart: '',
|
||||
},
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
@ -58,6 +60,12 @@ describe('Account Details Modal', () => {
|
||||
});
|
||||
|
||||
it('opens new tab when view block explorer is clicked', () => {
|
||||
wrapper.setProps({
|
||||
blockExplorerLinkText: {
|
||||
firstPart: 'viewOnEtherscan',
|
||||
secondPart: 'blockExplorerAccountAction',
|
||||
},
|
||||
});
|
||||
const modalButton = wrapper.find('.account-details-modal__button');
|
||||
const etherscanLink = modalButton.first();
|
||||
|
||||
@ -75,7 +83,10 @@ describe('Account Details Modal', () => {
|
||||
|
||||
it('sets blockexplorerview text when block explorer url in rpcPrefs exists', () => {
|
||||
const blockExplorerUrl = 'https://block.explorer';
|
||||
wrapper.setProps({ rpcPrefs: { blockExplorerUrl } });
|
||||
wrapper.setProps({
|
||||
rpcPrefs: { blockExplorerUrl },
|
||||
blockExplorerLinkText: { firstPart: 'blockExplorerView' },
|
||||
});
|
||||
|
||||
const modalButton = wrapper.find('.account-details-modal__button');
|
||||
const blockExplorerLink = modalButton.first().shallow();
|
||||
|
@ -16,6 +16,7 @@ import { EVENT } from '../../../../shared/constants/metametrics';
|
||||
import { TRANSACTION_TYPES } from '../../../../shared/constants/transaction';
|
||||
import { getURLHostName } from '../../../helpers/utils/util';
|
||||
import TransactionDecoding from '../transaction-decoding';
|
||||
import { NETWORKS_ROUTE } from '../../../helpers/constants/routes';
|
||||
|
||||
export default class TransactionListItemDetails extends PureComponent {
|
||||
static contextTypes = {
|
||||
@ -46,6 +47,9 @@ export default class TransactionListItemDetails extends PureComponent {
|
||||
senderNickname: PropTypes.string.isRequired,
|
||||
recipientNickname: PropTypes.string,
|
||||
transactionStatus: PropTypes.func,
|
||||
isCustomNetwork: PropTypes.bool,
|
||||
history: PropTypes.object,
|
||||
blockExplorerLinkText: PropTypes.object,
|
||||
};
|
||||
|
||||
state = {
|
||||
@ -56,26 +60,33 @@ export default class TransactionListItemDetails extends PureComponent {
|
||||
const {
|
||||
transactionGroup: { primaryTransaction },
|
||||
rpcPrefs,
|
||||
isCustomNetwork,
|
||||
history,
|
||||
onClose,
|
||||
} = this.props;
|
||||
const blockExplorerLink = getBlockExplorerLink(
|
||||
primaryTransaction,
|
||||
rpcPrefs,
|
||||
);
|
||||
|
||||
this.context.trackEvent({
|
||||
category: EVENT.CATEGORIES.TRANSACTIONS,
|
||||
event: 'Clicked Block Explorer Link',
|
||||
properties: {
|
||||
link_type: 'Transaction Block Explorer',
|
||||
action: 'Transaction Details',
|
||||
block_explorer_domain: getURLHostName(blockExplorerLink),
|
||||
legacy_event: true,
|
||||
},
|
||||
});
|
||||
if (!rpcPrefs.blockExplorerUrl && isCustomNetwork) {
|
||||
onClose();
|
||||
history.push(`${NETWORKS_ROUTE}#blockExplorerUrl`);
|
||||
} else {
|
||||
this.context.trackEvent({
|
||||
category: EVENT.CATEGORIES.TRANSACTIONS,
|
||||
event: 'Clicked Block Explorer Link',
|
||||
properties: {
|
||||
link_type: 'Transaction Block Explorer',
|
||||
action: 'Transaction Details',
|
||||
block_explorer_domain: getURLHostName(blockExplorerLink),
|
||||
},
|
||||
});
|
||||
|
||||
global.platform.openTab({
|
||||
url: blockExplorerLink,
|
||||
});
|
||||
global.platform.openTab({
|
||||
url: blockExplorerLink,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
handleCancel = (event) => {
|
||||
@ -136,6 +147,7 @@ export default class TransactionListItemDetails extends PureComponent {
|
||||
recipientNickname,
|
||||
showCancel,
|
||||
transactionStatus: TransactionStatus,
|
||||
blockExplorerLinkText,
|
||||
} = this.props;
|
||||
const {
|
||||
primaryTransaction: transaction,
|
||||
@ -191,7 +203,9 @@ export default class TransactionListItemDetails extends PureComponent {
|
||||
onClick={this.handleBlockExplorerClick}
|
||||
disabled={!hash}
|
||||
>
|
||||
{t('viewOnBlockExplorer')}
|
||||
{blockExplorerLinkText.firstPart === 'addBlockExplorer'
|
||||
? t('addBlockExplorer')
|
||||
: t('viewOnBlockExplorer')}
|
||||
</Button>
|
||||
</div>
|
||||
<div>
|
||||
|
@ -31,6 +31,15 @@ describe('TransactionListItemDetails Component', () => {
|
||||
initialTransaction: transaction,
|
||||
};
|
||||
|
||||
const rpcPrefs = {
|
||||
blockExplorerUrl: 'https://customblockexplorer.com/',
|
||||
};
|
||||
|
||||
const blockExplorerLinkText = {
|
||||
firstPart: 'addBlockExplorer',
|
||||
secondPart: '',
|
||||
};
|
||||
|
||||
const wrapper = shallow(
|
||||
<TransactionListItemDetails
|
||||
onClose={() => undefined}
|
||||
@ -42,6 +51,8 @@ describe('TransactionListItemDetails Component', () => {
|
||||
senderNickname="sender-nickname"
|
||||
recipientNickname="recipient-nickname"
|
||||
transactionStatus={TransactionStatus}
|
||||
rpcPrefs={rpcPrefs}
|
||||
blockExplorerLinkText={blockExplorerLinkText}
|
||||
/>,
|
||||
{ context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) } },
|
||||
);
|
||||
@ -77,6 +88,15 @@ describe('TransactionListItemDetails Component', () => {
|
||||
hasCancelled: false,
|
||||
};
|
||||
|
||||
const rpcPrefs = {
|
||||
blockExplorerUrl: 'https://customblockexplorer.com/',
|
||||
};
|
||||
|
||||
const blockExplorerLinkText = {
|
||||
firstPart: 'addBlockExplorer',
|
||||
secondPart: '',
|
||||
};
|
||||
|
||||
const wrapper = shallow(
|
||||
<TransactionListItemDetails
|
||||
onClose={() => undefined}
|
||||
@ -89,6 +109,8 @@ describe('TransactionListItemDetails Component', () => {
|
||||
senderNickname="sender-nickname"
|
||||
recipientNickname="recipient-nickname"
|
||||
transactionStatus={TransactionStatus}
|
||||
rpcPrefs={rpcPrefs}
|
||||
blockExplorerLinkText={blockExplorerLinkText}
|
||||
/>,
|
||||
{ context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) } },
|
||||
);
|
||||
@ -120,6 +142,15 @@ describe('TransactionListItemDetails Component', () => {
|
||||
initialTransaction: transaction,
|
||||
};
|
||||
|
||||
const rpcPrefs = {
|
||||
blockExplorerUrl: 'https://customblockexplorer.com/',
|
||||
};
|
||||
|
||||
const blockExplorerLinkText = {
|
||||
firstPart: 'addBlockExplorer',
|
||||
secondPart: '',
|
||||
};
|
||||
|
||||
const wrapper = shallow(
|
||||
<TransactionListItemDetails
|
||||
onClose={() => undefined}
|
||||
@ -131,6 +162,8 @@ describe('TransactionListItemDetails Component', () => {
|
||||
senderNickname="sender-nickname"
|
||||
recipientNickname="recipient-nickname"
|
||||
transactionStatus={TransactionStatus}
|
||||
rpcPrefs={rpcPrefs}
|
||||
blockExplorerLinkText={blockExplorerLinkText}
|
||||
/>,
|
||||
{ context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) } },
|
||||
);
|
||||
@ -165,6 +198,15 @@ describe('TransactionListItemDetails Component', () => {
|
||||
initialTransaction: transaction,
|
||||
};
|
||||
|
||||
const rpcPrefs = {
|
||||
blockExplorerUrl: 'https://customblockexplorer.com/',
|
||||
};
|
||||
|
||||
const blockExplorerLinkText = {
|
||||
firstPart: 'addBlockExplorer',
|
||||
secondPart: '',
|
||||
};
|
||||
|
||||
const wrapper = shallow(
|
||||
<TransactionListItemDetails
|
||||
onClose={() => undefined}
|
||||
@ -176,6 +218,8 @@ describe('TransactionListItemDetails Component', () => {
|
||||
senderNickname="sender-nickname"
|
||||
recipientNickname="recipient-nickname"
|
||||
transactionStatus={TransactionStatus}
|
||||
rpcPrefs={rpcPrefs}
|
||||
blockExplorerLinkText={blockExplorerLinkText}
|
||||
/>,
|
||||
{ context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) } },
|
||||
);
|
||||
|
@ -1,7 +1,11 @@
|
||||
import { connect } from 'react-redux';
|
||||
import { compose } from 'redux';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
import { tryReverseResolveAddress } from '../../../store/actions';
|
||||
import {
|
||||
getAddressBook,
|
||||
getBlockExplorerLinkText,
|
||||
getIsCustomNetwork,
|
||||
getRpcPrefsForCurrentProvider,
|
||||
getEnsResolutionByAddress,
|
||||
} from '../../../selectors';
|
||||
@ -25,11 +29,15 @@ const mapStateToProps = (state, ownProps) => {
|
||||
};
|
||||
const rpcPrefs = getRpcPrefsForCurrentProvider(state);
|
||||
|
||||
const isCustomNetwork = getIsCustomNetwork(state);
|
||||
|
||||
return {
|
||||
rpcPrefs,
|
||||
recipientEns,
|
||||
senderNickname: getNickName(senderAddress),
|
||||
recipientNickname: recipientAddress ? getNickName(recipientAddress) : null,
|
||||
isCustomNetwork,
|
||||
blockExplorerLinkText: getBlockExplorerLinkText(state),
|
||||
};
|
||||
};
|
||||
|
||||
@ -41,7 +49,7 @@ const mapDispatchToProps = (dispatch) => {
|
||||
};
|
||||
};
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps,
|
||||
export default compose(
|
||||
withRouter,
|
||||
connect(mapStateToProps, mapDispatchToProps),
|
||||
)(TransactionListItemDetails);
|
||||
|
@ -1,6 +1,7 @@
|
||||
import React, { useCallback, useContext } from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { I18nContext } from '../../../contexts/i18n';
|
||||
import Tooltip from '../tooltip';
|
||||
import Popover from '../popover';
|
||||
@ -9,7 +10,13 @@ import Identicon from '../identicon/identicon.component';
|
||||
import { shortenAddress } from '../../../helpers/utils/util';
|
||||
import CopyIcon from '../icon/copy-icon.component';
|
||||
import { useCopyToClipboard } from '../../../hooks/useCopyToClipboard';
|
||||
import { getUseTokenDetection, getTokenList } from '../../../selectors';
|
||||
import {
|
||||
getUseTokenDetection,
|
||||
getTokenList,
|
||||
getBlockExplorerLinkText,
|
||||
} from '../../../selectors';
|
||||
|
||||
import { NETWORKS_ROUTE } from '../../../helpers/constants/routes';
|
||||
|
||||
const NicknamePopover = ({
|
||||
address,
|
||||
@ -19,6 +26,7 @@ const NicknamePopover = ({
|
||||
explorerLink,
|
||||
}) => {
|
||||
const t = useContext(I18nContext);
|
||||
const history = useHistory();
|
||||
|
||||
const onAddClick = useCallback(() => {
|
||||
onAdd();
|
||||
@ -27,6 +35,17 @@ const NicknamePopover = ({
|
||||
const [copied, handleCopy] = useCopyToClipboard();
|
||||
const useTokenDetection = useSelector(getUseTokenDetection);
|
||||
const tokenList = useSelector(getTokenList);
|
||||
const blockExplorerLinkText = useSelector(getBlockExplorerLinkText);
|
||||
|
||||
const routeToAddBlockExplorerUrl = () => {
|
||||
history.push(`${NETWORKS_ROUTE}#blockExplorerUrl`);
|
||||
};
|
||||
|
||||
const openBlockExplorer = () => {
|
||||
global.platform.openTab({
|
||||
url: explorerLink,
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="nickname-popover">
|
||||
@ -66,16 +85,22 @@ const NicknamePopover = ({
|
||||
<Button
|
||||
type="link"
|
||||
className="nickname-popover__etherscan-link"
|
||||
onClick={() => {
|
||||
global.platform.openTab({
|
||||
url: explorerLink,
|
||||
});
|
||||
}}
|
||||
onClick={
|
||||
blockExplorerLinkText.firstPart === 'addBlockExplorer'
|
||||
? routeToAddBlockExplorerUrl
|
||||
: openBlockExplorer
|
||||
}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
title={t('etherscanView')}
|
||||
title={
|
||||
blockExplorerLinkText.firstPart === 'addBlockExplorer'
|
||||
? t('addBlockExplorer')
|
||||
: t('etherscanView')
|
||||
}
|
||||
>
|
||||
{t('viewOnBlockExplorer')}
|
||||
{blockExplorerLinkText.firstPart === 'addBlockExplorer'
|
||||
? t('addBlockExplorer')
|
||||
: t('viewOnBlockExplorer')}
|
||||
</Button>
|
||||
</div>
|
||||
<Button
|
||||
|
@ -1,8 +1,12 @@
|
||||
import React, { useContext, useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { I18nContext } from '../../../contexts/i18n';
|
||||
import { Menu, MenuItem } from '../../../components/ui/menu';
|
||||
import { getBlockExplorerLinkText } from '../../../selectors';
|
||||
import { NETWORKS_ROUTE } from '../../../helpers/constants/routes';
|
||||
|
||||
const AssetOptions = ({
|
||||
onRemove,
|
||||
@ -11,12 +15,22 @@ const AssetOptions = ({
|
||||
onViewTokenDetails,
|
||||
tokenSymbol,
|
||||
isNativeAsset,
|
||||
isEthNetwork,
|
||||
}) => {
|
||||
const t = useContext(I18nContext);
|
||||
const [assetOptionsButtonElement, setAssetOptionsButtonElement] =
|
||||
useState(null);
|
||||
const [assetOptionsOpen, setAssetOptionsOpen] = useState(false);
|
||||
const history = useHistory();
|
||||
const blockExplorerLinkText = useSelector(getBlockExplorerLinkText);
|
||||
|
||||
const routeToAddBlockExplorerUrl = () => {
|
||||
history.push(`${NETWORKS_ROUTE}#blockExplorerUrl`);
|
||||
};
|
||||
|
||||
const openBlockExplorer = () => {
|
||||
setAssetOptionsOpen(false);
|
||||
onClickBlockExplorer();
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -45,14 +59,18 @@ const AssetOptions = ({
|
||||
<MenuItem
|
||||
iconClassName="fas fa-external-link-alt asset-options__icon"
|
||||
data-testid="asset-options__etherscan"
|
||||
onClick={() => {
|
||||
setAssetOptionsOpen(false);
|
||||
onClickBlockExplorer();
|
||||
}}
|
||||
onClick={
|
||||
blockExplorerLinkText.firstPart === 'addBlockExplorer'
|
||||
? routeToAddBlockExplorerUrl
|
||||
: openBlockExplorer
|
||||
}
|
||||
>
|
||||
{isEthNetwork
|
||||
? t('viewOnEtherscan', [t('blockExplorerAssetAction')])
|
||||
: t('viewinExplorer', [t('blockExplorerAssetAction')])}
|
||||
{t(
|
||||
blockExplorerLinkText.firstPart,
|
||||
blockExplorerLinkText.secondPart === ''
|
||||
? null
|
||||
: [t('blockExplorerAssetAction')],
|
||||
)}
|
||||
</MenuItem>
|
||||
{isNativeAsset ? null : (
|
||||
<MenuItem
|
||||
@ -89,7 +107,6 @@ const isNotFunc = (p) => {
|
||||
};
|
||||
|
||||
AssetOptions.propTypes = {
|
||||
isEthNetwork: PropTypes.bool,
|
||||
isNativeAsset: PropTypes.bool,
|
||||
onClickBlockExplorer: PropTypes.func.isRequired,
|
||||
onViewAccountDetails: PropTypes.func.isRequired,
|
||||
|
@ -10,6 +10,7 @@ import {
|
||||
getCurrentChainId,
|
||||
getRpcPrefsForCurrentProvider,
|
||||
getSelectedAddress,
|
||||
getIsCustomNetwork,
|
||||
} from '../../../selectors/selectors';
|
||||
import { showModal } from '../../../store/actions';
|
||||
import { DEFAULT_ROUTE } from '../../../helpers/constants/routes';
|
||||
@ -31,6 +32,7 @@ export default function NativeAsset({ nativeCurrency }) {
|
||||
const history = useHistory();
|
||||
const accountLink = getAccountLink(address, chainId, rpcPrefs);
|
||||
const trackEvent = useContext(MetaMetricsContext);
|
||||
const isCustomNetwork = useSelector(getIsCustomNetwork);
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -38,7 +40,6 @@ export default function NativeAsset({ nativeCurrency }) {
|
||||
accountName={selectedAccountName}
|
||||
assetName={nativeCurrency}
|
||||
onBack={() => history.push(DEFAULT_ROUTE)}
|
||||
isEthNetwork={!rpcPrefs.blockExplorerUrl}
|
||||
optionsButton={
|
||||
<AssetOptions
|
||||
isNativeAsset
|
||||
@ -59,6 +60,7 @@ export default function NativeAsset({ nativeCurrency }) {
|
||||
onViewAccountDetails={() => {
|
||||
dispatch(showModal({ name: 'ACCOUNT_DETAILS' }));
|
||||
}}
|
||||
isCustomNetwork={isCustomNetwork}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
|
@ -9,6 +9,7 @@ import {
|
||||
getCurrentChainId,
|
||||
getSelectedIdentity,
|
||||
getRpcPrefsForCurrentProvider,
|
||||
getIsCustomNetwork,
|
||||
} from '../../../selectors/selectors';
|
||||
import {
|
||||
DEFAULT_ROUTE,
|
||||
@ -38,6 +39,8 @@ export default function TokenAsset({ token }) {
|
||||
);
|
||||
const trackEvent = useContext(MetaMetricsContext);
|
||||
|
||||
const isCustomNetwork = useSelector(getIsCustomNetwork);
|
||||
|
||||
return (
|
||||
<>
|
||||
<AssetNavigation
|
||||
@ -51,7 +54,7 @@ export default function TokenAsset({ token }) {
|
||||
showModal({ name: 'HIDE_TOKEN_CONFIRMATION', token, history }),
|
||||
)
|
||||
}
|
||||
isEthNetwork={!rpcPrefs.blockExplorerUrl}
|
||||
isCustomNetwork={isCustomNetwork}
|
||||
onClickBlockExplorer={() => {
|
||||
trackEvent({
|
||||
event: 'Clicked Block Explorer Link',
|
||||
|
@ -645,6 +645,7 @@ const NetworksForm = ({
|
||||
titleUnit={t('optionalWithParanthesis')}
|
||||
value={blockExplorerUrl}
|
||||
disabled={viewOnly}
|
||||
autoFocus={window.location.hash.split('#')[2] === 'blockExplorerUrl'}
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
|
@ -43,7 +43,9 @@ const NetworksTab = ({ addNewNetwork }) => {
|
||||
const environmentType = getEnvironmentType();
|
||||
const isFullScreen = environmentType === ENVIRONMENT_TYPE_FULLSCREEN;
|
||||
const shouldRenderNetworkForm =
|
||||
isFullScreen || Boolean(pathname.match(NETWORKS_FORM_ROUTE));
|
||||
isFullScreen ||
|
||||
Boolean(pathname.match(NETWORKS_FORM_ROUTE)) ||
|
||||
window.location.hash.split('#')[2] === 'blockExplorerUrl';
|
||||
|
||||
const frequentRpcListDetail = useSelector(getFrequentRpcListDetail);
|
||||
const provider = useSelector(getProvider);
|
||||
|
@ -18,6 +18,7 @@ import {
|
||||
BSC_DISPLAY_NAME,
|
||||
POLYGON_DISPLAY_NAME,
|
||||
AVALANCHE_DISPLAY_NAME,
|
||||
CHAIN_ID_TO_RPC_URL_MAP,
|
||||
} from '../../shared/constants/network';
|
||||
import {
|
||||
KEYRING_TYPES,
|
||||
@ -41,7 +42,11 @@ import {
|
||||
ALLOWED_DEV_SWAPS_CHAIN_IDS,
|
||||
} from '../../shared/constants/swaps';
|
||||
|
||||
import { shortenAddress, getAccountByAddress } from '../helpers/utils/util';
|
||||
import {
|
||||
shortenAddress,
|
||||
getAccountByAddress,
|
||||
getURLHostName,
|
||||
} from '../helpers/utils/util';
|
||||
import {
|
||||
getValueFromWeiHex,
|
||||
hexToDecimal,
|
||||
@ -1073,3 +1078,43 @@ export function getNewTokensImported(state) {
|
||||
export function getIsCustomNetworkListEnabled(state) {
|
||||
return state.metamask.customNetworkListEnabled;
|
||||
}
|
||||
|
||||
export function getIsCustomNetwork(state) {
|
||||
const chainId = getCurrentChainId(state);
|
||||
|
||||
return !CHAIN_ID_TO_RPC_URL_MAP[chainId];
|
||||
}
|
||||
|
||||
export function getBlockExplorerLinkText(
|
||||
state,
|
||||
accountDetailsModalComponent = false,
|
||||
) {
|
||||
const isCustomNetwork = getIsCustomNetwork(state);
|
||||
const rpcPrefs = getRpcPrefsForCurrentProvider(state);
|
||||
|
||||
let blockExplorerLinkText = {
|
||||
firstPart: 'addBlockExplorer',
|
||||
secondPart: '',
|
||||
};
|
||||
|
||||
if (rpcPrefs.blockExplorerUrl) {
|
||||
blockExplorerLinkText = accountDetailsModalComponent
|
||||
? {
|
||||
firstPart: 'blockExplorerView',
|
||||
secondPart: getURLHostName(rpcPrefs.blockExplorerUrl),
|
||||
}
|
||||
: {
|
||||
firstPart: 'viewinExplorer',
|
||||
secondPart: 'blockExplorerAccountAction',
|
||||
};
|
||||
} else if (isCustomNetwork === false) {
|
||||
blockExplorerLinkText = accountDetailsModalComponent
|
||||
? { firstPart: 'etherscanViewOn', secondPart: '' }
|
||||
: {
|
||||
firstPart: 'viewOnEtherscan',
|
||||
secondPart: 'blockExplorerAccountAction',
|
||||
};
|
||||
}
|
||||
|
||||
return blockExplorerLinkText;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user