use etherscan-link for account-link (#10590)

feature/default_network_editable
Brad Decker 4 years ago committed by GitHub
parent 38fe75b7d9
commit aa37e30c08
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 16
      test/unit/lib/account-link.test.js
  2. 6
      ui/app/components/app/menu-bar/account-options-menu.js
  3. 5
      ui/app/components/app/menu-bar/tests/menu-bar.test.js
  4. 6
      ui/app/components/app/modals/account-details-modal/account-details-modal.component.js
  5. 3
      ui/app/components/app/modals/account-details-modal/account-details-modal.container.js
  6. 9
      ui/app/components/app/modals/confirm-remove-account/confirm-remove-account.component.js
  7. 7
      ui/app/components/app/modals/confirm-remove-account/confirm-remove-account.container.js
  8. 9
      ui/app/pages/create-account/connect-hardware/account-list.js
  9. 34
      ui/app/pages/create-account/connect-hardware/index.js
  10. 23
      ui/lib/account-link.js

@ -1,4 +1,8 @@
import assert from 'assert';
import {
MAINNET_CHAIN_ID,
ROPSTEN_CHAIN_ID,
} from '../../../shared/constants/network';
import getAccountLink from '../../../ui/lib/account-link';
describe('Account link', function () {
@ -7,19 +11,19 @@ describe('Account link', function () {
const tests = [
{
expected: 'https://etherscan.io/address/0xabcd',
network: 1,
chainId: MAINNET_CHAIN_ID,
address: '0xabcd',
},
{
expected: 'https://ropsten.etherscan.io/address/0xdef0',
network: 3,
chainId: ROPSTEN_CHAIN_ID,
address: '0xdef0',
rpcPrefs: {},
},
{
// test handling of `blockExplorerUrl` for a custom RPC
expected: 'https://block.explorer/address/0xabcd',
network: 31,
chainId: '0x21',
address: '0xabcd',
rpcPrefs: {
blockExplorerUrl: 'https://block.explorer',
@ -28,7 +32,7 @@ describe('Account link', function () {
{
// test handling of trailing `/` in `blockExplorerUrl` for a custom RPC
expected: 'https://another.block.explorer/address/0xdef0',
network: 33,
chainId: '0x1f',
address: '0xdef0',
rpcPrefs: {
blockExplorerUrl: 'https://another.block.explorer/',
@ -36,8 +40,8 @@ describe('Account link', function () {
},
];
tests.forEach(({ expected, address, network, rpcPrefs }) => {
assert.equal(getAccountLink(address, network, rpcPrefs), expected);
tests.forEach(({ expected, address, chainId, rpcPrefs }) => {
assert.equal(getAccountLink(address, chainId, rpcPrefs), expected);
});
});
});

@ -8,8 +8,8 @@ import { CONNECTED_ROUTE } from '../../../helpers/constants/routes';
import { Menu, MenuItem } from '../../ui/menu';
import getAccountLink from '../../../../lib/account-link';
import {
getCurrentChainId,
getCurrentKeyring,
getCurrentNetwork,
getRpcPrefsForCurrentProvider,
getSelectedIdentity,
} from '../../../selectors';
@ -52,7 +52,7 @@ export default function AccountOptionsMenu({ anchorElement, onClose }) {
});
const keyring = useSelector(getCurrentKeyring);
const network = useSelector(getCurrentNetwork);
const chainId = useSelector(getCurrentChainId);
const rpcPrefs = useSelector(getRpcPrefsForCurrentProvider);
const selectedIdentity = useSelector(getSelectedIdentity);
@ -92,7 +92,7 @@ export default function AccountOptionsMenu({ anchorElement, onClose }) {
onClick={() => {
viewOnEtherscanEvent();
global.platform.openTab({
url: getAccountLink(address, network, rpcPrefs),
url: getAccountLink(address, chainId, rpcPrefs),
});
onClose();
}}

@ -4,11 +4,14 @@ import { Provider } from 'react-redux';
import configureStore from 'redux-mock-store';
import { mountWithRouter } from '../../../../../../test/lib/render-helpers';
import MenuBar from '..';
import { ROPSTEN_CHAIN_ID } from '../../../../../../shared/constants/network';
const initState = {
activeTab: {},
metamask: {
network: '1',
provider: {
chainId: ROPSTEN_CHAIN_ID,
},
selectedAddress: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc',
identities: {
'0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc': {

@ -9,7 +9,7 @@ import Button from '../../../ui/button';
export default class AccountDetailsModal extends Component {
static propTypes = {
selectedIdentity: PropTypes.object,
network: PropTypes.string,
chainId: PropTypes.string,
showExportPrivateKeyModal: PropTypes.func,
setAccountLabel: PropTypes.func,
keyrings: PropTypes.array,
@ -23,7 +23,7 @@ export default class AccountDetailsModal extends Component {
render() {
const {
selectedIdentity,
network,
chainId,
showExportPrivateKeyModal,
setAccountLabel,
keyrings,
@ -62,7 +62,7 @@ export default class AccountDetailsModal extends Component {
className="account-details-modal__button"
onClick={() => {
global.platform.openTab({
url: getAccountLink(address, network, rpcPrefs),
url: getAccountLink(address, chainId, rpcPrefs),
});
}}
>

@ -3,12 +3,13 @@ import { showModal, setAccountLabel } from '../../../../store/actions';
import {
getSelectedIdentity,
getRpcPrefsForCurrentProvider,
getCurrentChainId,
} from '../../../../selectors';
import AccountDetailsModal from './account-details-modal.component';
const mapStateToProps = (state) => {
return {
network: state.metamask.network,
chainId: getCurrentChainId(state),
selectedIdentity: getSelectedIdentity(state),
keyrings: state.metamask.keyrings,
rpcPrefs: getRpcPrefsForCurrentProvider(state),

@ -10,7 +10,8 @@ export default class ConfirmRemoveAccount extends Component {
hideModal: PropTypes.func.isRequired,
removeAccount: PropTypes.func.isRequired,
identity: PropTypes.object.isRequired,
network: PropTypes.string.isRequired,
chainId: PropTypes.string.isRequired,
rpcPrefs: PropTypes.object.isRequired,
};
static contextTypes = {
@ -49,7 +50,11 @@ export default class ConfirmRemoveAccount extends Component {
<div className="confirm-remove-account__account__link">
<a
className=""
href={getAccountLink(identity.address, this.props.network)}
href={getAccountLink(
identity.address,
this.props.chainId,
this.props.rpcPrefs,
)}
target="_blank"
rel="noopener noreferrer"
title={this.context.t('etherscanView')}

@ -1,12 +1,17 @@
import { connect } from 'react-redux';
import { compose } from 'redux';
import withModalProps from '../../../../helpers/higher-order-components/with-modal-props';
import {
getCurrentChainId,
getRpcPrefsForCurrentProvider,
} from '../../../../selectors';
import { removeAccount } from '../../../../store/actions';
import ConfirmRemoveAccount from './confirm-remove-account.component';
const mapStateToProps = (state) => {
return {
network: state.metamask.network,
chainId: getCurrentChainId(state),
rpcPrefs: getRpcPrefsForCurrentProvider(state),
};
};

@ -112,7 +112,11 @@ class AccountList extends Component {
</div>
<a
className="hw-account-list__item__link"
href={getAccountLink(account.address, this.props.network)}
href={getAccountLink(
account.address,
this.props.chainId,
this.props.rpcPrefs,
)}
target="_blank"
rel="noopener noreferrer"
title={this.context.t('etherscanView')}
@ -211,7 +215,8 @@ AccountList.propTypes = {
onAccountChange: PropTypes.func.isRequired,
onForgetDevice: PropTypes.func.isRequired,
getPage: PropTypes.func.isRequired,
network: PropTypes.string,
chainId: PropTypes.string,
rpcPrefs: PropTypes.object,
selectedAccounts: PropTypes.array.isRequired,
onUnlockAccounts: PropTypes.func,
onCancel: PropTypes.func,

@ -3,7 +3,9 @@ import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import * as actions from '../../../store/actions';
import {
getCurrentChainId,
getMetaMaskAccounts,
getRpcPrefsForCurrentProvider,
getMetaMaskAccountsConnected,
} from '../../../selectors';
import { formatBalance } from '../../../helpers/utils/util';
@ -257,7 +259,8 @@ class ConnectHardwareForm extends Component {
connectedAccounts={this.props.connectedAccounts}
selectedAccounts={this.state.selectedAccounts}
onAccountChange={this.onAccountChange}
network={this.props.network}
chainId={this.props.chainId}
rpcPrefs={this.props.rpcPrefs}
getPage={this.getPage}
onUnlockAccounts={this.onUnlockAccounts}
onForgetDevice={this.onForgetDevice}
@ -287,31 +290,22 @@ ConnectHardwareForm.propTypes = {
unlockHardwareWalletAccounts: PropTypes.func,
setHardwareWalletDefaultHdPath: PropTypes.func,
history: PropTypes.object,
network: PropTypes.string,
chainId: PropTypes.string,
rpcPrefs: PropTypes.object,
accounts: PropTypes.object,
connectedAccounts: PropTypes.array.isRequired,
defaultHdPaths: PropTypes.object,
mostRecentOverviewPage: PropTypes.string.isRequired,
};
const mapStateToProps = (state) => {
const {
metamask: { network },
} = state;
const accounts = getMetaMaskAccounts(state);
const connectedAccounts = getMetaMaskAccountsConnected(state);
const {
appState: { defaultHdPaths },
} = state;
return {
network,
accounts,
connectedAccounts,
defaultHdPaths,
mostRecentOverviewPage: getMostRecentOverviewPage(state),
};
};
const mapStateToProps = (state) => ({
chainId: getCurrentChainId(state),
rpcPrefs: getRpcPrefsForCurrentProvider(state),
accounts: getMetaMaskAccounts(state),
connectedAccounts: getMetaMaskAccountsConnected(state),
defaultHdPaths: state.appState.defaultHdPaths,
mostRecentOverviewPage: getMostRecentOverviewPage(state),
});
const mapDispatchToProps = (dispatch) => {
return {

@ -1,4 +1,6 @@
export default function getAccountLink(address, network, rpcPrefs) {
import { createAccountLinkForChain } from '@metamask/etherscan-link';
export default function getAccountLink(address, chainId, rpcPrefs) {
if (rpcPrefs && rpcPrefs.blockExplorerUrl) {
return `${rpcPrefs.blockExplorerUrl.replace(
/\/+$/u,
@ -6,22 +8,5 @@ export default function getAccountLink(address, network, rpcPrefs) {
)}/address/${address}`;
}
// eslint-disable-next-line radix
const net = parseInt(network);
switch (net) {
case 1: // main net
return `https://etherscan.io/address/${address}`;
case 2: // morden test net
return `https://morden.etherscan.io/address/${address}`;
case 3: // ropsten test net
return `https://ropsten.etherscan.io/address/${address}`;
case 4: // rinkeby test net
return `https://rinkeby.etherscan.io/address/${address}`;
case 42: // kovan test net
return `https://kovan.etherscan.io/address/${address}`;
case 5: // goerli test net
return `https://goerli.etherscan.io/address/${address}`;
default:
return '';
}
return createAccountLinkForChain(address, chainId);
}

Loading…
Cancel
Save