Commit 84663f2f authored by tom goriunov's avatar tom goriunov Committed by GitHub

Support redirects for known address discrepancies (#2799)

* Support redirects for known address discrepancies

Fixes #2793

* fix redirect to internal txs in the block

* add address user ops redirect
parent fdd6adee
import { useRouter } from 'next/router';
import React from 'react';
import getQueryParamString from './getQueryParamString';
export default function useEtherscanRedirects() {
const router = useRouter();
// The browser does not send the segment hash (or anchor) to the server,
// so we have to handle such redirects for the etherscan-like links on the client side.
React.useEffect(() => {
const segmentHash = window.location.hash;
if (segmentHash) {
switch (router.route) {
case '/tx/[hash]': {
const hash = getQueryParamString(router.query.hash);
switch (segmentHash) {
case '#statechange':
router.replace({
pathname: '/tx/[hash]',
query: { hash, tab: 'state' },
});
break;
case '#eventlog':
router.replace({
pathname: '/tx/[hash]',
query: { hash, tab: 'logs' },
});
break;
case '#aa':
router.replace({
pathname: '/tx/[hash]',
query: { hash, tab: 'user_ops' },
});
break;
case '#internal':
router.replace({
pathname: '/tx/[hash]',
query: { hash, tab: 'internal' },
});
break;
}
break;
}
case '/address/[hash]': {
const hash = getQueryParamString(router.query.hash);
switch (segmentHash) {
case '#internaltx':
router.replace({
pathname: '/address/[hash]',
query: { hash, tab: 'internal_txns' },
});
break;
case '#tokentxns':
router.replace({
pathname: '/address/[hash]',
query: { hash, tab: 'token_transfers' },
});
break;
case '#asset-tokens':
router.replace({
pathname: '/address/[hash]',
query: { hash, tab: 'tokens' },
});
break;
case '#asset-nfts':
router.replace({
pathname: '/address/[hash]',
query: { hash, tab: 'tokens_nfts' },
});
break;
case '#aatx':
router.replace({
pathname: '/address/[hash]',
query: { hash, tab: 'user_ops' },
});
break;
case '#code':
router.replace({
pathname: '/address/[hash]',
query: { hash, tab: 'contract' },
});
break;
case '#readContract':
router.replace({
pathname: '/address/[hash]',
query: { hash, tab: 'read_contract' },
});
break;
case '#writeContract':
router.replace({
pathname: '/address/[hash]',
query: { hash, tab: 'write_contract' },
});
break;
}
break;
}
case '/token/[hash]': {
const hash = getQueryParamString(router.query.hash);
switch (segmentHash) {
case '#balances':
router.replace({
pathname: '/token/[hash]',
query: { hash, tab: 'holders' },
});
break;
}
break;
}
case '/stats': {
switch (segmentHash) {
case '#section-contracts-data':
router.replace({
pathname: '/stats',
hash: 'contracts',
});
break;
}
break;
}
default:
break;
}
}
// run only on mount
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ ]);
}
const oldUrls = [ const OLD_UI_URLS = [
// ACCOUNT // ACCOUNT
{ {
source: '/account/tag_address', source: '/account/tag_address',
...@@ -266,9 +266,86 @@ const oldUrls = [ ...@@ -266,9 +266,86 @@ const oldUrls = [
}, },
]; ];
const ETHERSCAN_URLS = [
{
source: '/txsAA',
destination: '/ops',
},
{
source: '/txs',
has: [
{ type: 'query', key: 'block' },
],
destination: '/block/:block?tab=txs',
},
{
source: '/txsInternal',
has: [
{ type: 'query', key: 'block' },
],
destination: '/block/:block?tab=internal_txs',
},
{
source: '/txsInternal',
destination: '/internal-txs',
},
{
source: '/blocks_forked',
destination: '/blocks?tab=reorgs',
},
{
source: '/contractsVerified',
destination: '/verified-contracts',
},
{
source: '/verifyContract',
has: [
{ type: 'query', key: 'a' },
],
destination: '/address/:a/contract-verification',
},
{
source: '/verifyContract',
destination: '/contract-verification',
},
{
source: '/tokentxns',
destination: '/token-transfers',
},
{
source: '/nft/:hash/:id',
destination: '/token/:hash/instance/:id',
},
{
source: '/charts',
destination: '/stats',
},
{
source: '/nft-latest-mints',
destination: '/advanced-filter?transaction_types=ERC-1155%2CERC-721&methods=0xa0712d68&methods_names=mint',
},
{
source: '/nft-transfers',
destination: '/advanced-filter?transaction_types=ERC-1155%2CERC-721',
},
{
source: '/name-lookup-search',
destination: '/name-domains',
},
{
source: '/txsExit',
destination: '/withdrawals',
},
{
source: '/txsEnqueued',
destination: '/deposits',
},
];
async function redirects() { async function redirects() {
return [ return [
...oldUrls.map((item) => ({ ...item, permanent: false })), ...OLD_UI_URLS.map((item) => ({ ...item, permanent: false })),
...ETHERSCAN_URLS.map((item) => ({ ...item, permanent: true })),
]; ];
} }
......
...@@ -14,6 +14,7 @@ import useAddressProfileApiQuery from 'lib/hooks/useAddressProfileApiQuery'; ...@@ -14,6 +14,7 @@ import useAddressProfileApiQuery from 'lib/hooks/useAddressProfileApiQuery';
import useIsSafeAddress from 'lib/hooks/useIsSafeAddress'; import useIsSafeAddress from 'lib/hooks/useIsSafeAddress';
import getNetworkValidationActionText from 'lib/networks/getNetworkValidationActionText'; import getNetworkValidationActionText from 'lib/networks/getNetworkValidationActionText';
import getQueryParamString from 'lib/router/getQueryParamString'; import getQueryParamString from 'lib/router/getQueryParamString';
import useEtherscanRedirects from 'lib/router/useEtherscanRedirects';
import useSocketChannel from 'lib/socket/useSocketChannel'; import useSocketChannel from 'lib/socket/useSocketChannel';
import useSocketMessage from 'lib/socket/useSocketMessage'; import useSocketMessage from 'lib/socket/useSocketMessage';
import useFetchXStarScore from 'lib/xStarScore/useFetchXStarScore'; import useFetchXStarScore from 'lib/xStarScore/useFetchXStarScore';
...@@ -71,6 +72,9 @@ const AddressPageContent = () => { ...@@ -71,6 +72,9 @@ const AddressPageContent = () => {
const checkDomainName = useCheckDomainNameParam(hash); const checkDomainName = useCheckDomainNameParam(hash);
const checkAddressFormat = useCheckAddressFormat(hash); const checkAddressFormat = useCheckAddressFormat(hash);
useEtherscanRedirects();
const areQueriesEnabled = !checkDomainName && !checkAddressFormat; const areQueriesEnabled = !checkDomainName && !checkAddressFormat;
const addressQuery = useAddressQuery({ hash, isEnabled: areQueriesEnabled }); const addressQuery = useAddressQuery({ hash, isEnabled: areQueriesEnabled });
......
...@@ -2,6 +2,7 @@ import { Box } from '@chakra-ui/react'; ...@@ -2,6 +2,7 @@ import { Box } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import config from 'configs/app'; import config from 'configs/app';
import useEtherscanRedirects from 'lib/router/useEtherscanRedirects';
import PageTitle from 'ui/shared/Page/PageTitle'; import PageTitle from 'ui/shared/Page/PageTitle';
import ChartsWidgetsList from '../stats/ChartsWidgetsList'; import ChartsWidgetsList from '../stats/ChartsWidgetsList';
...@@ -24,6 +25,8 @@ const Stats = () => { ...@@ -24,6 +25,8 @@ const Stats = () => {
initialFilterQuery, initialFilterQuery,
} = useStats(); } = useStats();
useEtherscanRedirects();
return ( return (
<> <>
<PageTitle <PageTitle
......
...@@ -13,6 +13,7 @@ import useApiQuery, { getResourceKey } from 'lib/api/useApiQuery'; ...@@ -13,6 +13,7 @@ import useApiQuery, { getResourceKey } from 'lib/api/useApiQuery';
import useIsMobile from 'lib/hooks/useIsMobile'; import useIsMobile from 'lib/hooks/useIsMobile';
import * as metadata from 'lib/metadata'; import * as metadata from 'lib/metadata';
import getQueryParamString from 'lib/router/getQueryParamString'; import getQueryParamString from 'lib/router/getQueryParamString';
import useEtherscanRedirects from 'lib/router/useEtherscanRedirects';
import useSocketChannel from 'lib/socket/useSocketChannel'; import useSocketChannel from 'lib/socket/useSocketChannel';
import useSocketMessage from 'lib/socket/useSocketMessage'; import useSocketMessage from 'lib/socket/useSocketMessage';
import { NFT_TOKEN_TYPE_IDS } from 'lib/token/tokenTypes'; import { NFT_TOKEN_TYPE_IDS } from 'lib/token/tokenTypes';
...@@ -57,6 +58,7 @@ const TokenPageContent = () => { ...@@ -57,6 +58,7 @@ const TokenPageContent = () => {
const tab = getQueryParamString(router.query.tab); const tab = getQueryParamString(router.query.tab);
const ownerFilter = getQueryParamString(router.query.holder_address_hash) || undefined; const ownerFilter = getQueryParamString(router.query.holder_address_hash) || undefined;
useEtherscanRedirects();
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const tokenQuery = useTokenQuery(hashString); const tokenQuery = useTokenQuery(hashString);
......
...@@ -9,6 +9,7 @@ import useApiQuery from 'lib/api/useApiQuery'; ...@@ -9,6 +9,7 @@ import useApiQuery from 'lib/api/useApiQuery';
import { useAppContext } from 'lib/contexts/app'; import { useAppContext } from 'lib/contexts/app';
import throwOnResourceLoadError from 'lib/errors/throwOnResourceLoadError'; import throwOnResourceLoadError from 'lib/errors/throwOnResourceLoadError';
import getQueryParamString from 'lib/router/getQueryParamString'; import getQueryParamString from 'lib/router/getQueryParamString';
import useEtherscanRedirects from 'lib/router/useEtherscanRedirects';
import { publicClient } from 'lib/web3/client'; import { publicClient } from 'lib/web3/client';
import RoutedTabs from 'toolkit/components/RoutedTabs/RoutedTabs'; import RoutedTabs from 'toolkit/components/RoutedTabs/RoutedTabs';
import TextAd from 'ui/shared/ad/TextAd'; import TextAd from 'ui/shared/ad/TextAd';
...@@ -39,6 +40,9 @@ const TransactionPageContent = () => { ...@@ -39,6 +40,9 @@ const TransactionPageContent = () => {
const appProps = useAppContext(); const appProps = useAppContext();
const hash = getQueryParamString(router.query.hash); const hash = getQueryParamString(router.query.hash);
useEtherscanRedirects();
const txQuery = useTxQuery(); const txQuery = useTxQuery();
const tacOperationQuery = useApiQuery('tac:operation_by_tx_hash', { const tacOperationQuery = useApiQuery('tac:operation_by_tx_hash', {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment