mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-26 04:20:53 +01:00
Handling custom token decimal fetch failure due to network error (#10956)
This commit is contained in:
parent
6a73b7c998
commit
d4cb403d51
@ -486,7 +486,7 @@
|
|||||||
"message": "Some of your account data was backed up during a previous installation of MetaMask. This could include your settings, contacts, and tokens. Would you like to restore this data now?"
|
"message": "Some of your account data was backed up during a previous installation of MetaMask. This could include your settings, contacts, and tokens. Would you like to restore this data now?"
|
||||||
},
|
},
|
||||||
"decimal": {
|
"decimal": {
|
||||||
"message": "Decimals of Precision"
|
"message": "Token Decimal"
|
||||||
},
|
},
|
||||||
"decimalsMustZerotoTen": {
|
"decimalsMustZerotoTen": {
|
||||||
"message": "Decimals must be at least 0, and not over 36."
|
"message": "Decimals must be at least 0, and not over 36."
|
||||||
@ -2221,6 +2221,9 @@
|
|||||||
"tokenContractAddress": {
|
"tokenContractAddress": {
|
||||||
"message": "Token Contract Address"
|
"message": "Token Contract Address"
|
||||||
},
|
},
|
||||||
|
"tokenDecimalFetchFailed": {
|
||||||
|
"message": "Token decimal required."
|
||||||
|
},
|
||||||
"tokenSymbol": {
|
"tokenSymbol": {
|
||||||
"message": "Token Symbol"
|
"message": "Token Symbol"
|
||||||
},
|
},
|
||||||
@ -2352,6 +2355,10 @@
|
|||||||
"userName": {
|
"userName": {
|
||||||
"message": "Username"
|
"message": "Username"
|
||||||
},
|
},
|
||||||
|
"verifyThisTokenDecimalOn": {
|
||||||
|
"message": "Token decimal can be found on $1",
|
||||||
|
"description": "Points the user to etherscan as a place they can verify information about a token. $1 is replaced with the translation for \"etherscan\""
|
||||||
|
},
|
||||||
"verifyThisTokenOn": {
|
"verifyThisTokenOn": {
|
||||||
"message": "Verify this token on $1",
|
"message": "Verify this token on $1",
|
||||||
"description": "Points the user to etherscan as a place they can verify information about a token. $1 is replaced with the translation for \"etherscan\""
|
"description": "Points the user to etherscan as a place they can verify information about a token. $1 is replaced with the translation for \"etherscan\""
|
||||||
|
@ -100,7 +100,7 @@
|
|||||||
"@metamask/controllers": "^8.0.0",
|
"@metamask/controllers": "^8.0.0",
|
||||||
"@metamask/eth-ledger-bridge-keyring": "^0.5.0",
|
"@metamask/eth-ledger-bridge-keyring": "^0.5.0",
|
||||||
"@metamask/eth-token-tracker": "^3.0.1",
|
"@metamask/eth-token-tracker": "^3.0.1",
|
||||||
"@metamask/etherscan-link": "^2.0.0",
|
"@metamask/etherscan-link": "^2.1.0",
|
||||||
"@metamask/jazzicon": "^2.0.0",
|
"@metamask/jazzicon": "^2.0.0",
|
||||||
"@metamask/logo": "^2.5.0",
|
"@metamask/logo": "^2.5.0",
|
||||||
"@metamask/obs-store": "^5.0.0",
|
"@metamask/obs-store": "^5.0.0",
|
||||||
|
@ -13,7 +13,6 @@ const casedContractMap = Object.keys(contractMap).reduce((acc, base) => {
|
|||||||
}, {});
|
}, {});
|
||||||
|
|
||||||
const DEFAULT_SYMBOL = '';
|
const DEFAULT_SYMBOL = '';
|
||||||
const DEFAULT_DECIMALS = '0';
|
|
||||||
|
|
||||||
async function getSymbolFromContract(tokenAddress) {
|
async function getSymbolFromContract(tokenAddress) {
|
||||||
const token = util.getContractAtAddress(tokenAddress);
|
const token = util.getContractAtAddress(tokenAddress);
|
||||||
@ -78,25 +77,6 @@ async function getDecimals(tokenAddress) {
|
|||||||
return decimals;
|
return decimals;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function fetchSymbolAndDecimals(tokenAddress) {
|
|
||||||
let symbol, decimals;
|
|
||||||
|
|
||||||
try {
|
|
||||||
symbol = await getSymbol(tokenAddress);
|
|
||||||
decimals = await getDecimals(tokenAddress);
|
|
||||||
} catch (error) {
|
|
||||||
log.warn(
|
|
||||||
`symbol() and decimal() calls for token at address ${tokenAddress} resulted in error:`,
|
|
||||||
error,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
symbol: symbol || DEFAULT_SYMBOL,
|
|
||||||
decimals: decimals || DEFAULT_DECIMALS,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getSymbolAndDecimals(tokenAddress, existingTokens = []) {
|
export async function getSymbolAndDecimals(tokenAddress, existingTokens = []) {
|
||||||
const existingToken = existingTokens.find(
|
const existingToken = existingTokens.find(
|
||||||
({ address }) => tokenAddress === address,
|
({ address }) => tokenAddress === address,
|
||||||
@ -123,7 +103,7 @@ export async function getSymbolAndDecimals(tokenAddress, existingTokens = []) {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
symbol: symbol || DEFAULT_SYMBOL,
|
symbol: symbol || DEFAULT_SYMBOL,
|
||||||
decimals: decimals || DEFAULT_DECIMALS,
|
decimals,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
import { getTokenTrackerLink } from '@metamask/etherscan-link';
|
||||||
import { checkExistingAddresses } from '../../helpers/utils/util';
|
import { checkExistingAddresses } from '../../helpers/utils/util';
|
||||||
import { tokenInfoGetter } from '../../helpers/utils/token-util';
|
import { tokenInfoGetter } from '../../helpers/utils/token-util';
|
||||||
import { CONFIRM_ADD_TOKEN_ROUTE } from '../../helpers/constants/routes';
|
import { CONFIRM_ADD_TOKEN_ROUTE } from '../../helpers/constants/routes';
|
||||||
@ -8,6 +9,10 @@ import PageContainer from '../../components/ui/page-container';
|
|||||||
import { Tabs, Tab } from '../../components/ui/tabs';
|
import { Tabs, Tab } from '../../components/ui/tabs';
|
||||||
import { isValidHexAddress } from '../../../shared/modules/hexstring-utils';
|
import { isValidHexAddress } from '../../../shared/modules/hexstring-utils';
|
||||||
import { addHexPrefix } from '../../../app/scripts/lib/util';
|
import { addHexPrefix } from '../../../app/scripts/lib/util';
|
||||||
|
import ActionableMessage from '../swaps/actionable-message';
|
||||||
|
import Typography from '../../components/ui/typography';
|
||||||
|
import { TYPOGRAPHY, FONT_WEIGHT } from '../../helpers/constants/design-system';
|
||||||
|
import Button from '../../components/ui/button';
|
||||||
import TokenList from './token-list';
|
import TokenList from './token-list';
|
||||||
import TokenSearch from './token-search';
|
import TokenSearch from './token-search';
|
||||||
|
|
||||||
@ -30,6 +35,8 @@ class AddToken extends Component {
|
|||||||
identities: PropTypes.object,
|
identities: PropTypes.object,
|
||||||
showSearchTab: PropTypes.bool.isRequired,
|
showSearchTab: PropTypes.bool.isRequired,
|
||||||
mostRecentOverviewPage: PropTypes.string.isRequired,
|
mostRecentOverviewPage: PropTypes.string.isRequired,
|
||||||
|
chainId: PropTypes.string,
|
||||||
|
rpcPrefs: PropTypes.object,
|
||||||
};
|
};
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
@ -42,8 +49,9 @@ class AddToken extends Component {
|
|||||||
customAddressError: null,
|
customAddressError: null,
|
||||||
customSymbolError: null,
|
customSymbolError: null,
|
||||||
customDecimalsError: null,
|
customDecimalsError: null,
|
||||||
autoFilled: false,
|
|
||||||
forceEditSymbol: false,
|
forceEditSymbol: false,
|
||||||
|
symbolAutoFilled: false,
|
||||||
|
decimalAutoFilled: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
@ -148,10 +156,11 @@ class AddToken extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async attemptToAutoFillTokenParams(address) {
|
async attemptToAutoFillTokenParams(address) {
|
||||||
const { symbol = '', decimals = 0 } = await this.tokenInfoGetter(address);
|
const { symbol = '', decimals } = await this.tokenInfoGetter(address);
|
||||||
|
|
||||||
const autoFilled = Boolean(symbol && decimals);
|
const symbolAutoFilled = Boolean(symbol);
|
||||||
this.setState({ autoFilled });
|
const decimalAutoFilled = Boolean(decimals);
|
||||||
|
this.setState({ symbolAutoFilled, decimalAutoFilled });
|
||||||
this.handleCustomSymbolChange(symbol || '');
|
this.handleCustomSymbolChange(symbol || '');
|
||||||
this.handleCustomDecimalsChange(decimals);
|
this.handleCustomDecimalsChange(decimals);
|
||||||
}
|
}
|
||||||
@ -162,7 +171,8 @@ class AddToken extends Component {
|
|||||||
customAddress,
|
customAddress,
|
||||||
customAddressError: null,
|
customAddressError: null,
|
||||||
tokenSelectorError: null,
|
tokenSelectorError: null,
|
||||||
autoFilled: false,
|
symbolAutoFilled: false,
|
||||||
|
decimalAutoFilled: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
const addressIsValid = isValidHexAddress(customAddress, {
|
const addressIsValid = isValidHexAddress(customAddress, {
|
||||||
@ -213,16 +223,18 @@ class AddToken extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleCustomDecimalsChange(value) {
|
handleCustomDecimalsChange(value) {
|
||||||
const customDecimals = value.trim();
|
let customDecimals;
|
||||||
const validDecimals =
|
|
||||||
customDecimals !== null &&
|
|
||||||
customDecimals !== '' &&
|
|
||||||
customDecimals >= MIN_DECIMAL_VALUE &&
|
|
||||||
customDecimals <= MAX_DECIMAL_VALUE;
|
|
||||||
let customDecimalsError = null;
|
let customDecimalsError = null;
|
||||||
|
|
||||||
if (!validDecimals) {
|
if (value) {
|
||||||
customDecimalsError = this.context.t('decimalsMustZerotoTen');
|
customDecimals = Number(value.trim());
|
||||||
|
customDecimalsError =
|
||||||
|
value < MIN_DECIMAL_VALUE || value > MAX_DECIMAL_VALUE
|
||||||
|
? this.context.t('decimalsMustZerotoTen')
|
||||||
|
: null;
|
||||||
|
} else {
|
||||||
|
customDecimals = '';
|
||||||
|
customDecimalsError = this.context.t('tokenDecimalFetchFailed');
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState({ customDecimals, customDecimalsError });
|
this.setState({ customDecimals, customDecimalsError });
|
||||||
@ -236,10 +248,23 @@ class AddToken extends Component {
|
|||||||
customAddressError,
|
customAddressError,
|
||||||
customSymbolError,
|
customSymbolError,
|
||||||
customDecimalsError,
|
customDecimalsError,
|
||||||
autoFilled,
|
|
||||||
forceEditSymbol,
|
forceEditSymbol,
|
||||||
|
symbolAutoFilled,
|
||||||
|
decimalAutoFilled,
|
||||||
} = this.state;
|
} = this.state;
|
||||||
|
|
||||||
|
const { chainId, rpcPrefs } = this.props;
|
||||||
|
const blockExplorerTokenLink = getTokenTrackerLink(
|
||||||
|
customAddress,
|
||||||
|
chainId,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
{ blockExplorerUrl: rpcPrefs?.blockExplorerUrl ?? null },
|
||||||
|
);
|
||||||
|
const blockExplorerLabel = rpcPrefs?.blockExplorerUrl
|
||||||
|
? new URL(blockExplorerTokenLink).hostname
|
||||||
|
: this.context.t('etherscan');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="add-token__custom-token-form">
|
<div className="add-token__custom-token-form">
|
||||||
<TextField
|
<TextField
|
||||||
@ -260,7 +285,7 @@ class AddToken extends Component {
|
|||||||
<span className="add-token__custom-symbol__label">
|
<span className="add-token__custom-symbol__label">
|
||||||
{this.context.t('tokenSymbol')}
|
{this.context.t('tokenSymbol')}
|
||||||
</span>
|
</span>
|
||||||
{autoFilled && !forceEditSymbol && (
|
{symbolAutoFilled && !forceEditSymbol && (
|
||||||
<div
|
<div
|
||||||
className="add-token__custom-symbol__edit"
|
className="add-token__custom-symbol__edit"
|
||||||
onClick={() => this.setState({ forceEditSymbol: true })}
|
onClick={() => this.setState({ forceEditSymbol: true })}
|
||||||
@ -276,7 +301,7 @@ class AddToken extends Component {
|
|||||||
error={customSymbolError}
|
error={customSymbolError}
|
||||||
fullWidth
|
fullWidth
|
||||||
margin="normal"
|
margin="normal"
|
||||||
disabled={autoFilled && !forceEditSymbol}
|
disabled={symbolAutoFilled && !forceEditSymbol}
|
||||||
/>
|
/>
|
||||||
<TextField
|
<TextField
|
||||||
id="custom-decimals"
|
id="custom-decimals"
|
||||||
@ -284,13 +309,47 @@ class AddToken extends Component {
|
|||||||
type="number"
|
type="number"
|
||||||
value={customDecimals}
|
value={customDecimals}
|
||||||
onChange={(e) => this.handleCustomDecimalsChange(e.target.value)}
|
onChange={(e) => this.handleCustomDecimalsChange(e.target.value)}
|
||||||
error={customDecimalsError}
|
error={customDecimals ? customDecimalsError : null}
|
||||||
fullWidth
|
fullWidth
|
||||||
margin="normal"
|
margin="normal"
|
||||||
disabled={autoFilled}
|
disabled={decimalAutoFilled}
|
||||||
min={MIN_DECIMAL_VALUE}
|
min={MIN_DECIMAL_VALUE}
|
||||||
max={MAX_DECIMAL_VALUE}
|
max={MAX_DECIMAL_VALUE}
|
||||||
/>
|
/>
|
||||||
|
{customDecimals === '' && (
|
||||||
|
<ActionableMessage
|
||||||
|
message={
|
||||||
|
<>
|
||||||
|
<Typography
|
||||||
|
variant={TYPOGRAPHY.H7}
|
||||||
|
fontWeight={FONT_WEIGHT.BOLD}
|
||||||
|
>
|
||||||
|
{this.context.t('tokenDecimalFetchFailed')}
|
||||||
|
</Typography>
|
||||||
|
<Typography
|
||||||
|
variant={TYPOGRAPHY.H7}
|
||||||
|
fontWeight={FONT_WEIGHT.NORMAL}
|
||||||
|
>
|
||||||
|
{this.context.t('verifyThisTokenDecimalOn', [
|
||||||
|
<Button
|
||||||
|
type="link"
|
||||||
|
key="add-token-verify-token-decimal"
|
||||||
|
className="add-token__link"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
target="_blank"
|
||||||
|
href={blockExplorerTokenLink}
|
||||||
|
>
|
||||||
|
{blockExplorerLabel}
|
||||||
|
</Button>,
|
||||||
|
])}
|
||||||
|
</Typography>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
type="warning"
|
||||||
|
withRightButton
|
||||||
|
className="add-token__decimal-warning"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -2,12 +2,20 @@ import { connect } from 'react-redux';
|
|||||||
|
|
||||||
import { setPendingTokens, clearPendingTokens } from '../../store/actions';
|
import { setPendingTokens, clearPendingTokens } from '../../store/actions';
|
||||||
import { getMostRecentOverviewPage } from '../../ducks/history/history';
|
import { getMostRecentOverviewPage } from '../../ducks/history/history';
|
||||||
import { getIsMainnet } from '../../selectors/selectors';
|
import {
|
||||||
|
getIsMainnet,
|
||||||
|
getRpcPrefsForCurrentProvider,
|
||||||
|
} from '../../selectors/selectors';
|
||||||
import AddToken from './add-token.component';
|
import AddToken from './add-token.component';
|
||||||
|
|
||||||
const mapStateToProps = (state) => {
|
const mapStateToProps = (state) => {
|
||||||
const {
|
const {
|
||||||
metamask: { identities, tokens, pendingTokens },
|
metamask: {
|
||||||
|
identities,
|
||||||
|
tokens,
|
||||||
|
pendingTokens,
|
||||||
|
provider: { chainId },
|
||||||
|
},
|
||||||
} = state;
|
} = state;
|
||||||
return {
|
return {
|
||||||
identities,
|
identities,
|
||||||
@ -15,6 +23,8 @@ const mapStateToProps = (state) => {
|
|||||||
tokens,
|
tokens,
|
||||||
pendingTokens,
|
pendingTokens,
|
||||||
showSearchTab: getIsMainnet(state) || process.env.IN_TEST === 'true',
|
showSearchTab: getIsMainnet(state) || process.env.IN_TEST === 'true',
|
||||||
|
chainId,
|
||||||
|
rpcPrefs: getRpcPrefsForCurrentProvider(state),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -82,7 +82,7 @@ describe('Add Token', () => {
|
|||||||
|
|
||||||
expect(
|
expect(
|
||||||
wrapper.find('AddToken').instance().state.customDecimals,
|
wrapper.find('AddToken').instance().state.customDecimals,
|
||||||
).toStrictEqual(tokenPrecision);
|
).toStrictEqual(Number(tokenPrecision));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('next', () => {
|
it('next', () => {
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
@import 'token-list/index';
|
@import 'token-list/index';
|
||||||
|
|
||||||
.add-token {
|
.add-token {
|
||||||
|
$self: &;
|
||||||
|
|
||||||
&__custom-token-form {
|
&__custom-token-form {
|
||||||
padding: 8px 16px 16px;
|
padding: 8px 16px 16px;
|
||||||
|
|
||||||
@ -13,6 +15,9 @@
|
|||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
& #{$self}__decimal-warning {
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__search-token {
|
&__search-token {
|
||||||
@ -41,4 +46,12 @@
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__link {
|
||||||
|
@include H7;
|
||||||
|
|
||||||
|
display: inline;
|
||||||
|
color: $primary-blue;
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ import {
|
|||||||
loadRelativeTimeFormatLocaleData,
|
loadRelativeTimeFormatLocaleData,
|
||||||
} from '../helpers/utils/i18n-helper';
|
} from '../helpers/utils/i18n-helper';
|
||||||
import { getMethodDataAsync } from '../helpers/utils/transactions.util';
|
import { getMethodDataAsync } from '../helpers/utils/transactions.util';
|
||||||
import { fetchSymbolAndDecimals } from '../helpers/utils/token-util';
|
import { getSymbolAndDecimals } from '../helpers/utils/token-util';
|
||||||
import switchDirection from '../helpers/utils/switch-direction';
|
import switchDirection from '../helpers/utils/switch-direction';
|
||||||
import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../shared/constants/app';
|
import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../shared/constants/app';
|
||||||
import { hasUnconfirmedTransactions } from '../helpers/utils/confirm-tx.util';
|
import { hasUnconfirmedTransactions } from '../helpers/utils/confirm-tx.util';
|
||||||
@ -24,7 +24,6 @@ import { switchedToUnconnectedAccount } from '../ducks/alerts/unconnected-accoun
|
|||||||
import { getUnconnectedAccountAlertEnabledness } from '../ducks/metamask/metamask';
|
import { getUnconnectedAccountAlertEnabledness } from '../ducks/metamask/metamask';
|
||||||
import { toChecksumHexAddress } from '../../shared/modules/hexstring-utils';
|
import { toChecksumHexAddress } from '../../shared/modules/hexstring-utils';
|
||||||
import { LISTED_CONTRACT_ADDRESSES } from '../../shared/constants/tokens';
|
import { LISTED_CONTRACT_ADDRESSES } from '../../shared/constants/tokens';
|
||||||
import { toChecksumHexAddress } from '../../shared/modules/hexstring-utils';
|
|
||||||
import * as actionConstants from './actionConstants';
|
import * as actionConstants from './actionConstants';
|
||||||
|
|
||||||
let background = null;
|
let background = null;
|
||||||
@ -2252,7 +2251,7 @@ export function setPendingTokens(pendingTokens) {
|
|||||||
const { customToken = {}, selectedTokens = {} } = pendingTokens;
|
const { customToken = {}, selectedTokens = {} } = pendingTokens;
|
||||||
const { address, symbol, decimals } = customToken;
|
const { address, symbol, decimals } = customToken;
|
||||||
const tokens =
|
const tokens =
|
||||||
address && symbol && decimals
|
address && symbol && decimals >= 0 <= 36
|
||||||
? {
|
? {
|
||||||
...selectedTokens,
|
...selectedTokens,
|
||||||
[address]: {
|
[address]: {
|
||||||
@ -2654,12 +2653,10 @@ export function getTokenParams(tokenAddress) {
|
|||||||
dispatch(loadingTokenParamsStarted());
|
dispatch(loadingTokenParamsStarted());
|
||||||
log.debug(`loadingTokenParams`);
|
log.debug(`loadingTokenParams`);
|
||||||
|
|
||||||
return fetchSymbolAndDecimals(tokenAddress, existingTokens).then(
|
return getSymbolAndDecimals(tokenAddress).then(({ symbol, decimals }) => {
|
||||||
({ symbol, decimals }) => {
|
dispatch(addToken(tokenAddress, symbol, Number(decimals)));
|
||||||
dispatch(addToken(tokenAddress, symbol, Number(decimals)));
|
dispatch(loadingTokenParamsFinished());
|
||||||
dispatch(loadingTokenParamsFinished());
|
});
|
||||||
},
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2739,10 +2739,10 @@
|
|||||||
human-standard-token-abi "^1.0.2"
|
human-standard-token-abi "^1.0.2"
|
||||||
safe-event-emitter "^1.0.1"
|
safe-event-emitter "^1.0.1"
|
||||||
|
|
||||||
"@metamask/etherscan-link@^2.0.0":
|
"@metamask/etherscan-link@^2.1.0":
|
||||||
version "2.0.0"
|
version "2.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/@metamask/etherscan-link/-/etherscan-link-2.0.0.tgz#89035736515a39532ba1142d87b9a8c2b4f920f1"
|
resolved "https://registry.yarnpkg.com/@metamask/etherscan-link/-/etherscan-link-2.1.0.tgz#c0be8e68445b7b83cf85bcc03a56cdf8e256c973"
|
||||||
integrity sha512-/YS32hS2UTTxs0KyUmAgaDj1w4dzAvOrT+p4TJtpICeH3E/k51r2FO0Or7WJJI/mpzTqNKgcH5yyS2oCtupGiA==
|
integrity sha512-ADuWlTUkFfN2vXlz81Bg/0BA+XRor+CdK1055p6k7H6BLIPoDKn9SBOFld9haQFuR9cKh/JYHcnlSIv5R4fUEw==
|
||||||
|
|
||||||
"@metamask/forwarder@^1.1.0":
|
"@metamask/forwarder@^1.1.0":
|
||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
|
Loading…
Reference in New Issue
Block a user