diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 625576060..6365a9d05 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -1937,7 +1937,8 @@ "message": "Using the best quote" }, "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": { "message": "View $1" diff --git a/app/_locales/es/messages.json b/app/_locales/es/messages.json index bced8493f..1981d8ceb 100644 --- a/app/_locales/es/messages.json +++ b/app/_locales/es/messages.json @@ -1805,7 +1805,8 @@ "message": "Utilizando la mejor cotización" }, "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": { "message": "Ver $1" diff --git a/app/_locales/es_419/messages.json b/app/_locales/es_419/messages.json index 14efe2258..24943d0b5 100644 --- a/app/_locales/es_419/messages.json +++ b/app/_locales/es_419/messages.json @@ -1805,7 +1805,8 @@ "message": "Utilizando la mejor cotización" }, "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": { "message": "Ver $1" diff --git a/app/_locales/hi/messages.json b/app/_locales/hi/messages.json index 4af8b5008..226fef67d 100644 --- a/app/_locales/hi/messages.json +++ b/app/_locales/hi/messages.json @@ -1772,7 +1772,8 @@ "message": "अज्ञात" }, "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": { "message": "$1 देखें" diff --git a/app/_locales/id/messages.json b/app/_locales/id/messages.json index a2505c17d..4d651bf8f 100644 --- a/app/_locales/id/messages.json +++ b/app/_locales/id/messages.json @@ -1772,7 +1772,8 @@ "message": "Tidak diketahui" }, "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": { "message": "Lihat $1" diff --git a/app/_locales/it/messages.json b/app/_locales/it/messages.json index b5aaab033..80955408b 100644 --- a/app/_locales/it/messages.json +++ b/app/_locales/it/messages.json @@ -1828,7 +1828,8 @@ "message": "Quotazione migliore" }, "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": { "message": "Vedi $1" diff --git a/app/_locales/ja/messages.json b/app/_locales/ja/messages.json index 732166a40..9289ed536 100644 --- a/app/_locales/ja/messages.json +++ b/app/_locales/ja/messages.json @@ -1805,7 +1805,8 @@ "message": "最適な見積を使用する" }, "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": { "message": "$1 を表示" diff --git a/app/_locales/ko/messages.json b/app/_locales/ko/messages.json index de7953333..3f57e7128 100644 --- a/app/_locales/ko/messages.json +++ b/app/_locales/ko/messages.json @@ -1769,7 +1769,8 @@ "message": "알 수 없음" }, "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": { "message": "$1 보기" diff --git a/app/_locales/ru/messages.json b/app/_locales/ru/messages.json index df22aa710..e7a51e108 100644 --- a/app/_locales/ru/messages.json +++ b/app/_locales/ru/messages.json @@ -1772,7 +1772,8 @@ "message": "Неизвестный" }, "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": { "message": "Просмотреть $1" diff --git a/app/_locales/tl/messages.json b/app/_locales/tl/messages.json index 49e83c002..5e43560b1 100644 --- a/app/_locales/tl/messages.json +++ b/app/_locales/tl/messages.json @@ -1769,7 +1769,8 @@ "message": "Hindi Alam" }, "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": { "message": "Tingnan ang $1" diff --git a/app/_locales/vi/messages.json b/app/_locales/vi/messages.json index 2c01eb147..31b5b1929 100644 --- a/app/_locales/vi/messages.json +++ b/app/_locales/vi/messages.json @@ -1772,7 +1772,8 @@ "message": "Không xác định" }, "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": { "message": "Xem $1" diff --git a/app/_locales/zh_CN/messages.json b/app/_locales/zh_CN/messages.json index 00129d3f3..996408591 100644 --- a/app/_locales/zh_CN/messages.json +++ b/app/_locales/zh_CN/messages.json @@ -1805,7 +1805,8 @@ "message": "使用最好的报价" }, "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": { "message": "查看 $1" diff --git a/shared/constants/swaps.js b/shared/constants/swaps.js index afe312683..007fdb618 100644 --- a/shared/constants/swaps.js +++ b/shared/constants/swaps.js @@ -51,6 +51,8 @@ const BNB_CHAIN_ID = '0x38'; const SWAPS_TESTNET_CHAIN_ID = '0x539'; 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 = { [MAINNET_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, [BNB_CHAIN_ID]: BNB_SWAPS_TOKEN_OBJECT, }; + +export const SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP = { + [BNB_CHAIN_ID]: BSC_DEFAULT_BLOCK_EXPLORER_URL, +}; diff --git a/ui/app/pages/swaps/awaiting-swap/awaiting-swap.js b/ui/app/pages/swaps/awaiting-swap/awaiting-swap.js index 7f39c12e8..af21ce29b 100644 --- a/ui/app/pages/swaps/awaiting-swap/awaiting-swap.js +++ b/ui/app/pages/swaps/awaiting-swap/awaiting-swap.js @@ -3,6 +3,7 @@ import React, { useContext, useRef, useState } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import PropTypes from 'prop-types'; import { useHistory } from 'react-router-dom'; +import { createCustomExplorerLink } from '@metamask/etherscan-link'; import { I18nContext } from '../../../contexts/i18n'; import { useNewMetricEvent } from '../../../hooks/useMetricEvent'; import { MetaMetricsContext } from '../../../contexts/metametrics.new'; @@ -31,7 +32,9 @@ import { ERROR_FETCHING_QUOTES, QUOTES_NOT_AVAILABLE_ERROR, OFFLINE_FOR_MAINTENANCE, + SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP, } 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 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 SwapsFooter from '../swaps-footer'; import { getBlockExplorerUrlForTx } from '../../../../../shared/modules/transaction.utils'; + import SwapFailureIcon from './swap-failure-icon'; import SwapSuccessIcon from './swap-success-icon'; import QuotesTimeoutIcon from './quotes-timeout-icon'; @@ -105,8 +109,21 @@ export default function AwaitingSwap({ category: 'swaps', }); - const blockExplorerUrl = - txHash && getBlockExplorerUrlForTx({ chainId, hash: txHash }, rpcPrefs); + let blockExplorerUrl; + 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 statusImage; @@ -138,7 +155,7 @@ export default function AwaitingSwap({ ); } else if (errorKey === QUOTES_EXPIRED_ERROR) { @@ -177,7 +194,7 @@ export default function AwaitingSwap({ ); } else if (!errorKey && swapComplete) { @@ -196,7 +213,7 @@ export default function AwaitingSwap({ ); } diff --git a/ui/app/pages/swaps/awaiting-swap/view-on-ether-scan-link/view-on-ether-scan-link.js b/ui/app/pages/swaps/awaiting-swap/view-on-ether-scan-link/view-on-ether-scan-link.js index bb3d07cda..15fb7d081 100644 --- a/ui/app/pages/swaps/awaiting-swap/view-on-ether-scan-link/view-on-ether-scan-link.js +++ b/ui/app/pages/swaps/awaiting-swap/view-on-ether-scan-link/view-on-ether-scan-link.js @@ -18,7 +18,7 @@ export default function ViewOnEtherScanLink({ onClick={() => global.platform.openTab({ url: blockExplorerUrl })} > {isCustomBlockExplorerUrl - ? t('viewOnCustomBlockExplorer', [blockExplorerUrl]) + ? t('viewOnCustomBlockExplorer', [new URL(blockExplorerUrl).hostname]) : t('viewOnEtherscan')} ); diff --git a/ui/app/pages/swaps/build-quote/build-quote.js b/ui/app/pages/swaps/build-quote/build-quote.js index d106fa18d..dce6ffafc 100644 --- a/ui/app/pages/swaps/build-quote/build-quote.js +++ b/ui/app/pages/swaps/build-quote/build-quote.js @@ -4,6 +4,10 @@ import { useDispatch, useSelector } from 'react-redux'; import classnames from 'classnames'; import { uniqBy, isEqual } from 'lodash'; import { useHistory } from 'react-router-dom'; +import { + createCustomTokenTrackerLink, + createTokenTrackerLinkForChain, +} from '@metamask/etherscan-link'; import { MetaMetricsContext } from '../../../contexts/metametrics.new'; import { useTokensToSearch, @@ -34,6 +38,7 @@ import { getConversionRate, getCurrentCurrency, getCurrentChainId, + getRpcPrefsForCurrentProvider, } from '../../../selectors'; import { getValueFromWeiHex, @@ -49,6 +54,7 @@ import { isSwapsDefaultTokenAddress, isSwapsDefaultTokenSymbol, } from '../../../../../shared/modules/swaps.utils'; +import { SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP } from '../../../../../shared/constants/swaps'; import { resetSwapsPostFetchState, removeToken } from '../../../store/actions'; import { fetchTokenPrice, fetchTokenBalance } from '../swaps.util'; @@ -90,6 +96,7 @@ export default function BuildQuote({ const toToken = useSelector(getToToken) || destinationTokenInfo; const defaultSwapsToken = useSelector(getSwapsDefaultToken); const chainId = useSelector(getCurrentChainId); + const rpcPrefs = useSelector(getRpcPrefsForCurrentProvider); const tokenConversionRates = useSelector(getTokenExchangeRates, isEqual); 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 { address: toAddress } = toToken || {}; const onToSelect = useCallback( @@ -412,17 +443,18 @@ export default function BuildQuote({ : t('swapTokenVerificationNoSource')}
- {t('verifyThisTokenOn', [ - - {t('etherscan')} - , - ])} + {blockExplorerTokenLink && + t('verifyThisTokenOn', [ + + {blockExplorerLabel} + , + ])}
} @@ -436,7 +468,10 @@ export default function BuildQuote({ } type="warning" withRightButton - infoTooltipText={t('swapVerifyTokenExplanation')} + infoTooltipText={ + blockExplorerTokenLink && + t('swapVerifyTokenExplanation', [blockExplorerLabel]) + } /> ) : (
@@ -446,23 +481,29 @@ export default function BuildQuote({ > {t('swapTokenVerificationSources', [occurances])} - {t('swapTokenVerificationMessage', [ - - {t('etherscan')} - , - ])} - + {blockExplorerTokenLink && ( + <> + {t('swapTokenVerificationMessage', [ + + {blockExplorerLabel} + , + ])} + + + )}
))}