1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-23 09:52:26 +01:00

Use correct block explorer name and link in swaps when on custom network (#10743)

* Use correct block explorer name and link in swaps when on custom network.

* Fix up custom etherscan link code in build-quote.js

* Use blockExplorerUrl hostname instead of 'blockExplorerBaseUrl'

* Use correct etherscan-link method for token links in build-quote

* Create correct token link in build-quote for mainnet AND custom networks

* Block explorer url improvements in awaiting-swap.js and build-quote.js

* Use swapVerifyTokenExplanation message with substitutable block explorer for all applicable locales

* Ensure that block explorer links are not shown in awaiting-swap if no url is available
This commit is contained in:
Dan J Miller 2021-03-29 10:24:27 -02:30 committed by GitHub
parent 254164aec4
commit d8fd4b8271
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 123 additions and 47 deletions

View File

@ -1937,7 +1937,8 @@
"message": "Using the best quote" "message": "Using the best quote"
}, },
"swapVerifyTokenExplanation": { "swapVerifyTokenExplanation": {
"message": "Multiple tokens can use the same name and symbol. Check Etherscan to verify this is the token you're looking for." "message": "Multiple tokens can use the same name and symbol. Check $1 to verify this is the token you're looking for.",
"description": "This appears in a tooltip next to the verifyThisTokenOn message. It gives the user more information about why they should check the token on a block explorer. $1 will be the name or url of the block explorer, which will be the translation of 'etherscan' or a block explorer url specified for a custom network."
}, },
"swapViewToken": { "swapViewToken": {
"message": "View $1" "message": "View $1"

View File

@ -1805,7 +1805,8 @@
"message": "Utilizando la mejor cotización" "message": "Utilizando la mejor cotización"
}, },
"swapVerifyTokenExplanation": { "swapVerifyTokenExplanation": {
"message": "Varios tokens pueden usar el mismo nombre y símbolo. Verifique Etherscan para verificar que este es el token que está buscando." "message": "Varios tokens pueden usar el mismo nombre y símbolo. Verifique $1 para verificar que este es el token que está buscando.",
"description": "This appears in a tooltip next to the verifyThisTokenOn message. It gives the user more information about why they should check the token on a block explorer. $1 will be the name or url of the block explorer, which will be the translation of 'etherscan' or a block explorer url specified for a custom network."
}, },
"swapViewToken": { "swapViewToken": {
"message": "Ver $1" "message": "Ver $1"

View File

@ -1805,7 +1805,8 @@
"message": "Utilizando la mejor cotización" "message": "Utilizando la mejor cotización"
}, },
"swapVerifyTokenExplanation": { "swapVerifyTokenExplanation": {
"message": "Varios tokens pueden usar el mismo nombre y símbolo. Verifique Etherscan para verificar que este es el token que está buscando." "message": "Varios tokens pueden usar el mismo nombre y símbolo. Verifique $1 para verificar que este es el token que está buscando.",
"description": "This appears in a tooltip next to the verifyThisTokenOn message. It gives the user more information about why they should check the token on a block explorer. $1 will be the name or url of the block explorer, which will be the translation of 'etherscan' or a block explorer url specified for a custom network."
}, },
"swapViewToken": { "swapViewToken": {
"message": "Ver $1" "message": "Ver $1"

View File

@ -1772,7 +1772,8 @@
"message": "अज्ञात" "message": "अज्ञात"
}, },
"swapVerifyTokenExplanation": { "swapVerifyTokenExplanation": {
"message": "एकाधिक टोकन एक ही नाम और प्रतीक का उपयोग कर सकते हैं। यह सत्यापित करने के लिए Etherscan की जाँच करें कि यह वही टोकन है, जिसकी आप तलाश कर रहे हैं।" "message": "एकाधिक टोकन एक ही नाम और प्रतीक का उपयोग कर सकते हैं। यह सत्यापित करने के लिए $1 की जाँच करें कि यह वही टोकन है, जिसकी आप तलाश कर रहे हैं।",
"description": "This appears in a tooltip next to the verifyThisTokenOn message. It gives the user more information about why they should check the token on a block explorer. $1 will be the name or url of the block explorer, which will be the translation of 'etherscan' or a block explorer url specified for a custom network."
}, },
"swapViewToken": { "swapViewToken": {
"message": "$1 देखें" "message": "$1 देखें"

View File

@ -1772,7 +1772,8 @@
"message": "Tidak diketahui" "message": "Tidak diketahui"
}, },
"swapVerifyTokenExplanation": { "swapVerifyTokenExplanation": {
"message": "Beberapa token dapat menggunakan simbol dan nama yang sama. Periksa Etherscan untuk memverifikasi inilah token yang Anda cari." "message": "Beberapa token dapat menggunakan simbol dan nama yang sama. Periksa $1 untuk memverifikasi inilah token yang Anda cari.",
"description": "This appears in a tooltip next to the verifyThisTokenOn message. It gives the user more information about why they should check the token on a block explorer. $1 will be the name or url of the block explorer, which will be the translation of 'etherscan' or a block explorer url specified for a custom network."
}, },
"swapViewToken": { "swapViewToken": {
"message": "Lihat $1" "message": "Lihat $1"

View File

@ -1828,7 +1828,8 @@
"message": "Quotazione migliore" "message": "Quotazione migliore"
}, },
"swapVerifyTokenExplanation": { "swapVerifyTokenExplanation": {
"message": "Più token possono usare lo stesso nome e simbolo. Verifica su Etherscan che questo sia il token che stai cercando." "message": "Più token possono usare lo stesso nome e simbolo. Verifica su $1 che questo sia il token che stai cercando.",
"description": "This appears in a tooltip next to the verifyThisTokenOn message. It gives the user more information about why they should check the token on a block explorer. $1 will be the name or url of the block explorer, which will be the translation of 'etherscan' or a block explorer url specified for a custom network."
}, },
"swapViewToken": { "swapViewToken": {
"message": "Vedi $1" "message": "Vedi $1"

View File

@ -1805,7 +1805,8 @@
"message": "最適な見積を使用する" "message": "最適な見積を使用する"
}, },
"swapVerifyTokenExplanation": { "swapVerifyTokenExplanation": {
"message": "複数のトークンが同じ名前とシンボルであることがあります。Etherscanで実際のトークンでを確認してください。" "message": "複数のトークンが同じ名前とシンボルであることがあります。$1で実際のトークンでを確認してください。",
"description": "This appears in a tooltip next to the verifyThisTokenOn message. It gives the user more information about why they should check the token on a block explorer. $1 will be the name or url of the block explorer, which will be the translation of 'etherscan' or a block explorer url specified for a custom network."
}, },
"swapViewToken": { "swapViewToken": {
"message": "$1 を表示" "message": "$1 を表示"

View File

@ -1769,7 +1769,8 @@
"message": "알 수 없음" "message": "알 수 없음"
}, },
"swapVerifyTokenExplanation": { "swapVerifyTokenExplanation": {
"message": "여러 토큰이 같은 이름과 기호를 사용할 수 있습니다. Etherscan을 확인하여 이것이 원하는 토큰인지 확인하세요." "message": "여러 토큰이 같은 이름과 기호를 사용할 수 있습니다. $1을 확인하여 이것이 원하는 토큰인지 확인하세요.",
"description": "This appears in a tooltip next to the verifyThisTokenOn message. It gives the user more information about why they should check the token on a block explorer. $1 will be the name or url of the block explorer, which will be the translation of 'etherscan' or a block explorer url specified for a custom network."
}, },
"swapViewToken": { "swapViewToken": {
"message": "$1 보기" "message": "$1 보기"

View File

@ -1772,7 +1772,8 @@
"message": "Неизвестный" "message": "Неизвестный"
}, },
"swapVerifyTokenExplanation": { "swapVerifyTokenExplanation": {
"message": "Несколько токенов могут использовать одно и то же имя и символ. Проверьте Etherscan, чтобы убедиться, что это именно тот токен, который вы ищете." "message": "Несколько токенов могут использовать одно и то же имя и символ. Проверьте $1, чтобы убедиться, что это именно тот токен, который вы ищете.",
"description": "This appears in a tooltip next to the verifyThisTokenOn message. It gives the user more information about why they should check the token on a block explorer. $1 will be the name or url of the block explorer, which will be the translation of 'etherscan' or a block explorer url specified for a custom network."
}, },
"swapViewToken": { "swapViewToken": {
"message": "Просмотреть $1" "message": "Просмотреть $1"

View File

@ -1769,7 +1769,8 @@
"message": "Hindi Alam" "message": "Hindi Alam"
}, },
"swapVerifyTokenExplanation": { "swapVerifyTokenExplanation": {
"message": "Maaaring gamitin ng maraming token ang iisang pangalan at simbolo. Suriin ang Etherscan para ma-verify na ito ang token na hinahanap mo." "message": "Maaaring gamitin ng maraming token ang iisang pangalan at simbolo. Suriin ang $1 para ma-verify na ito ang token na hinahanap mo.",
"description": "This appears in a tooltip next to the verifyThisTokenOn message. It gives the user more information about why they should check the token on a block explorer. $1 will be the name or url of the block explorer, which will be the translation of 'etherscan' or a block explorer url specified for a custom network."
}, },
"swapViewToken": { "swapViewToken": {
"message": "Tingnan ang $1" "message": "Tingnan ang $1"

View File

@ -1772,7 +1772,8 @@
"message": "Không xác định" "message": "Không xác định"
}, },
"swapVerifyTokenExplanation": { "swapVerifyTokenExplanation": {
"message": "Nhiều token có thể dùng cùng một tên và ký hiệu. Hãy kiểm tra trên Etherscan để xác minh xem đây có phải là token bạn đang tìm kiếm không." "message": "Nhiều token có thể dùng cùng một tên và ký hiệu. Hãy kiểm tra trên $1 để xác minh xem đây có phải là token bạn đang tìm kiếm không.",
"description": "This appears in a tooltip next to the verifyThisTokenOn message. It gives the user more information about why they should check the token on a block explorer. $1 will be the name or url of the block explorer, which will be the translation of 'etherscan' or a block explorer url specified for a custom network."
}, },
"swapViewToken": { "swapViewToken": {
"message": "Xem $1" "message": "Xem $1"

View File

@ -1805,7 +1805,8 @@
"message": "使用最好的报价" "message": "使用最好的报价"
}, },
"swapVerifyTokenExplanation": { "swapVerifyTokenExplanation": {
"message": "多个代币可以使用相同的名称和符号。检查 Etherscan以太坊浏览器以确认这是您正在寻找的代币。" "message": "多个代币可以使用相同的名称和符号。检查 $1以太坊浏览器以确认这是您正在寻找的代币。",
"description": "This appears in a tooltip next to the verifyThisTokenOn message. It gives the user more information about why they should check the token on a block explorer. $1 will be the name or url of the block explorer, which will be the translation of 'etherscan' or a block explorer url specified for a custom network."
}, },
"swapViewToken": { "swapViewToken": {
"message": "查看 $1" "message": "查看 $1"

View File

@ -51,6 +51,8 @@ const BNB_CHAIN_ID = '0x38';
const SWAPS_TESTNET_CHAIN_ID = '0x539'; const SWAPS_TESTNET_CHAIN_ID = '0x539';
const SWAPS_TESTNET_HOST = 'https://metaswap-api.airswap-dev.codefi.network'; const SWAPS_TESTNET_HOST = 'https://metaswap-api.airswap-dev.codefi.network';
const BSC_DEFAULT_BLOCK_EXPLORER_URL = 'https://bscscan.com/';
export const ALLOWED_SWAPS_CHAIN_IDS = { export const ALLOWED_SWAPS_CHAIN_IDS = {
[MAINNET_CHAIN_ID]: true, [MAINNET_CHAIN_ID]: true,
[SWAPS_TESTNET_CHAIN_ID]: true, [SWAPS_TESTNET_CHAIN_ID]: true,
@ -74,3 +76,7 @@ export const SWAPS_CHAINID_DEFAULT_TOKEN_MAP = {
[SWAPS_TESTNET_CHAIN_ID]: TEST_ETH_SWAPS_TOKEN_OBJECT, [SWAPS_TESTNET_CHAIN_ID]: TEST_ETH_SWAPS_TOKEN_OBJECT,
[BNB_CHAIN_ID]: BNB_SWAPS_TOKEN_OBJECT, [BNB_CHAIN_ID]: BNB_SWAPS_TOKEN_OBJECT,
}; };
export const SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP = {
[BNB_CHAIN_ID]: BSC_DEFAULT_BLOCK_EXPLORER_URL,
};

View File

@ -3,6 +3,7 @@ import React, { useContext, useRef, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { useHistory } from 'react-router-dom'; import { useHistory } from 'react-router-dom';
import { createCustomExplorerLink } from '@metamask/etherscan-link';
import { I18nContext } from '../../../contexts/i18n'; import { I18nContext } from '../../../contexts/i18n';
import { useNewMetricEvent } from '../../../hooks/useMetricEvent'; import { useNewMetricEvent } from '../../../hooks/useMetricEvent';
import { MetaMetricsContext } from '../../../contexts/metametrics.new'; import { MetaMetricsContext } from '../../../contexts/metametrics.new';
@ -31,7 +32,9 @@ import {
ERROR_FETCHING_QUOTES, ERROR_FETCHING_QUOTES,
QUOTES_NOT_AVAILABLE_ERROR, QUOTES_NOT_AVAILABLE_ERROR,
OFFLINE_FOR_MAINTENANCE, OFFLINE_FOR_MAINTENANCE,
SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP,
} from '../../../../../shared/constants/swaps'; } from '../../../../../shared/constants/swaps';
import { CHAIN_ID_TO_TYPE_MAP as VALID_INFURA_CHAIN_IDS } from '../../../../../shared/constants/network';
import { isSwapsDefaultTokenSymbol } from '../../../../../shared/modules/swaps.utils'; import { isSwapsDefaultTokenSymbol } from '../../../../../shared/modules/swaps.utils';
import PulseLoader from '../../../components/ui/pulse-loader'; import PulseLoader from '../../../components/ui/pulse-loader';
@ -40,6 +43,7 @@ import { ASSET_ROUTE, DEFAULT_ROUTE } from '../../../helpers/constants/routes';
import { getRenderableNetworkFeesForQuote } from '../swaps.util'; import { getRenderableNetworkFeesForQuote } from '../swaps.util';
import SwapsFooter from '../swaps-footer'; import SwapsFooter from '../swaps-footer';
import { getBlockExplorerUrlForTx } from '../../../../../shared/modules/transaction.utils'; import { getBlockExplorerUrlForTx } from '../../../../../shared/modules/transaction.utils';
import SwapFailureIcon from './swap-failure-icon'; import SwapFailureIcon from './swap-failure-icon';
import SwapSuccessIcon from './swap-success-icon'; import SwapSuccessIcon from './swap-success-icon';
import QuotesTimeoutIcon from './quotes-timeout-icon'; import QuotesTimeoutIcon from './quotes-timeout-icon';
@ -105,8 +109,21 @@ export default function AwaitingSwap({
category: 'swaps', category: 'swaps',
}); });
const blockExplorerUrl = let blockExplorerUrl;
txHash && getBlockExplorerUrlForTx({ chainId, hash: txHash }, rpcPrefs); if (txHash && rpcPrefs.blockExplorerUrl) {
blockExplorerUrl = getBlockExplorerUrlForTx({ hash: txHash }, rpcPrefs);
} else if (txHash && SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP[chainId]) {
blockExplorerUrl = createCustomExplorerLink(
txHash,
SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP[chainId],
);
} else if (txHash && VALID_INFURA_CHAIN_IDS[chainId]) {
blockExplorerUrl = getBlockExplorerUrlForTx({ chainId, hash: txHash });
}
const isCustomBlockExplorerUrl =
SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP[chainId] ||
rpcPrefs.blockExplorerUrl;
let headerText; let headerText;
let statusImage; let statusImage;
@ -138,7 +155,7 @@ export default function AwaitingSwap({
<ViewOnEtherScanLink <ViewOnEtherScanLink
txHash={txHash} txHash={txHash}
blockExplorerUrl={blockExplorerUrl} blockExplorerUrl={blockExplorerUrl}
isCustomBlockExplorerUrl={Boolean(rpcPrefs.blockExplorerUrl)} isCustomBlockExplorerUrl={isCustomBlockExplorerUrl}
/> />
); );
} else if (errorKey === QUOTES_EXPIRED_ERROR) { } else if (errorKey === QUOTES_EXPIRED_ERROR) {
@ -177,7 +194,7 @@ export default function AwaitingSwap({
<ViewOnEtherScanLink <ViewOnEtherScanLink
txHash={txHash} txHash={txHash}
blockExplorerUrl={blockExplorerUrl} blockExplorerUrl={blockExplorerUrl}
isCustomBlockExplorerUrl={Boolean(rpcPrefs.blockExplorerUrl)} isCustomBlockExplorerUrl={isCustomBlockExplorerUrl}
/> />
); );
} else if (!errorKey && swapComplete) { } else if (!errorKey && swapComplete) {
@ -196,7 +213,7 @@ export default function AwaitingSwap({
<ViewOnEtherScanLink <ViewOnEtherScanLink
txHash={txHash} txHash={txHash}
blockExplorerUrl={blockExplorerUrl} blockExplorerUrl={blockExplorerUrl}
isCustomBlockExplorerUrl={Boolean(rpcPrefs.blockExplorerUrl)} isCustomBlockExplorerUrl={isCustomBlockExplorerUrl}
/> />
); );
} }

View File

@ -18,7 +18,7 @@ export default function ViewOnEtherScanLink({
onClick={() => global.platform.openTab({ url: blockExplorerUrl })} onClick={() => global.platform.openTab({ url: blockExplorerUrl })}
> >
{isCustomBlockExplorerUrl {isCustomBlockExplorerUrl
? t('viewOnCustomBlockExplorer', [blockExplorerUrl]) ? t('viewOnCustomBlockExplorer', [new URL(blockExplorerUrl).hostname])
: t('viewOnEtherscan')} : t('viewOnEtherscan')}
</div> </div>
); );

View File

@ -4,6 +4,10 @@ import { useDispatch, useSelector } from 'react-redux';
import classnames from 'classnames'; import classnames from 'classnames';
import { uniqBy, isEqual } from 'lodash'; import { uniqBy, isEqual } from 'lodash';
import { useHistory } from 'react-router-dom'; import { useHistory } from 'react-router-dom';
import {
createCustomTokenTrackerLink,
createTokenTrackerLinkForChain,
} from '@metamask/etherscan-link';
import { MetaMetricsContext } from '../../../contexts/metametrics.new'; import { MetaMetricsContext } from '../../../contexts/metametrics.new';
import { import {
useTokensToSearch, useTokensToSearch,
@ -34,6 +38,7 @@ import {
getConversionRate, getConversionRate,
getCurrentCurrency, getCurrentCurrency,
getCurrentChainId, getCurrentChainId,
getRpcPrefsForCurrentProvider,
} from '../../../selectors'; } from '../../../selectors';
import { import {
getValueFromWeiHex, getValueFromWeiHex,
@ -49,6 +54,7 @@ import {
isSwapsDefaultTokenAddress, isSwapsDefaultTokenAddress,
isSwapsDefaultTokenSymbol, isSwapsDefaultTokenSymbol,
} from '../../../../../shared/modules/swaps.utils'; } from '../../../../../shared/modules/swaps.utils';
import { SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP } from '../../../../../shared/constants/swaps';
import { resetSwapsPostFetchState, removeToken } from '../../../store/actions'; import { resetSwapsPostFetchState, removeToken } from '../../../store/actions';
import { fetchTokenPrice, fetchTokenBalance } from '../swaps.util'; import { fetchTokenPrice, fetchTokenBalance } from '../swaps.util';
@ -90,6 +96,7 @@ export default function BuildQuote({
const toToken = useSelector(getToToken) || destinationTokenInfo; const toToken = useSelector(getToToken) || destinationTokenInfo;
const defaultSwapsToken = useSelector(getSwapsDefaultToken); const defaultSwapsToken = useSelector(getSwapsDefaultToken);
const chainId = useSelector(getCurrentChainId); const chainId = useSelector(getCurrentChainId);
const rpcPrefs = useSelector(getRpcPrefsForCurrentProvider);
const tokenConversionRates = useSelector(getTokenExchangeRates, isEqual); const tokenConversionRates = useSelector(getTokenExchangeRates, isEqual);
const conversionRate = useSelector(getConversionRate); const conversionRate = useSelector(getConversionRate);
@ -215,6 +222,30 @@ export default function BuildQuote({
); );
}; };
let blockExplorerTokenLink;
let blockExplorerLabel;
if (rpcPrefs.blockExplorerUrl) {
blockExplorerTokenLink = createCustomTokenTrackerLink(
selectedToToken.address,
rpcPrefs.blockExplorerUrl,
);
blockExplorerLabel = new URL(rpcPrefs.blockExplorerUrl).hostname;
} else if (SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP[chainId]) {
blockExplorerTokenLink = createCustomTokenTrackerLink(
selectedToToken.address,
SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP[chainId],
);
blockExplorerLabel = new URL(
SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP[chainId],
).hostname;
} else {
blockExplorerTokenLink = createTokenTrackerLinkForChain(
selectedToToken.address,
chainId,
);
blockExplorerLabel = t('etherscan');
}
const { destinationTokenAddedForSwap } = fetchParams || {}; const { destinationTokenAddedForSwap } = fetchParams || {};
const { address: toAddress } = toToken || {}; const { address: toAddress } = toToken || {};
const onToSelect = useCallback( const onToSelect = useCallback(
@ -412,17 +443,18 @@ export default function BuildQuote({
: t('swapTokenVerificationNoSource')} : t('swapTokenVerificationNoSource')}
</div> </div>
<div> <div>
{t('verifyThisTokenOn', [ {blockExplorerTokenLink &&
<a t('verifyThisTokenOn', [
className="build-quote__token-etherscan-link build-quote__underline" <a
key="build-quote-etherscan-link" className="build-quote__token-etherscan-link build-quote__underline"
href={`https://etherscan.io/token/${selectedToToken.address}`} key="build-quote-etherscan-link"
target="_blank" href={blockExplorerTokenLink}
rel="noopener noreferrer" target="_blank"
> rel="noopener noreferrer"
{t('etherscan')} >
</a>, {blockExplorerLabel}
])} </a>,
])}
</div> </div>
</div> </div>
} }
@ -436,7 +468,10 @@ export default function BuildQuote({
} }
type="warning" type="warning"
withRightButton withRightButton
infoTooltipText={t('swapVerifyTokenExplanation')} infoTooltipText={
blockExplorerTokenLink &&
t('swapVerifyTokenExplanation', [blockExplorerLabel])
}
/> />
) : ( ) : (
<div className="build-quote__token-message"> <div className="build-quote__token-message">
@ -446,23 +481,29 @@ export default function BuildQuote({
> >
{t('swapTokenVerificationSources', [occurances])} {t('swapTokenVerificationSources', [occurances])}
</span> </span>
{t('swapTokenVerificationMessage', [ {blockExplorerTokenLink && (
<a <>
className="build-quote__token-etherscan-link" {t('swapTokenVerificationMessage', [
key="build-quote-etherscan-link" <a
href={`https://etherscan.io/token/${selectedToToken.address}`} className="build-quote__token-etherscan-link"
target="_blank" key="build-quote-etherscan-link"
rel="noopener noreferrer" href={blockExplorerTokenLink}
> target="_blank"
{t('etherscan')} rel="noopener noreferrer"
</a>, >
])} {blockExplorerLabel}
<InfoTooltip </a>,
position="top" ])}
contentText={t('swapVerifyTokenExplanation')} <InfoTooltip
containerClassName="build-quote__token-tooltip-container" position="top"
key="token-verification-info-tooltip" contentText={t('swapVerifyTokenExplanation', [
/> blockExplorerLabel,
])}
containerClassName="build-quote__token-tooltip-container"
key="token-verification-info-tooltip"
/>
</>
)}
</div> </div>
))} ))}
<div className="build-quote__slippage-buttons-container"> <div className="build-quote__slippage-buttons-container">