Commit c4f6b563 authored by tom goriunov's avatar tom goriunov Committed by GitHub

404 for unknown transaction (#1697)

* 404 for unknown transaction

Fixes #1689

* add helper for displaying custom error screen
parent 089e6674
......@@ -6,6 +6,7 @@ import throwOnResourceLoadError from 'lib/errors/throwOnResourceLoadError';
import getQueryParamString from 'lib/router/getQueryParamString';
import AddressCounterItem from 'ui/address/details/AddressCounterItem';
import ServiceDegradationWarning from 'ui/shared/alerts/ServiceDegradationWarning';
import isCustomAppError from 'ui/shared/AppError/isCustomAppError';
import DataFetchAlert from 'ui/shared/DataFetchAlert';
import DetailsInfoItem from 'ui/shared/DetailsInfoItem';
import DetailsSponsoredItem from 'ui/shared/DetailsSponsoredItem';
......@@ -59,15 +60,16 @@ const AddressDetails = ({ addressQuery, scrollRef }: Props) => {
has_validated_blocks: false,
}), [ addressHash ]);
const is404Error = addressQuery.isError && 'status' in addressQuery.error && addressQuery.error.status === 404;
const is422Error = addressQuery.isError && 'status' in addressQuery.error && addressQuery.error.status === 422;
if (addressQuery.isError && is422Error) {
throwOnResourceLoadError(addressQuery);
}
if (addressQuery.isError && !is404Error) {
return <DataFetchAlert/>;
// error handling (except 404 codes)
if (addressQuery.isError) {
if (isCustomAppError(addressQuery.error)) {
const is404Error = addressQuery.isError && 'status' in addressQuery.error && addressQuery.error.status === 404;
if (!is404Error) {
throwOnResourceLoadError(addressQuery);
}
} else {
return <DataFetchAlert/>;
}
}
const data = addressQuery.isError ? error404Data : addressQuery.data;
......
......@@ -7,6 +7,7 @@ import getQueryParamString from 'lib/router/getQueryParamString';
import { BLOB } from 'stubs/blobs';
import BlobInfo from 'ui/blob/BlobInfo';
import TextAd from 'ui/shared/ad/TextAd';
import isCustomAppError from 'ui/shared/AppError/isCustomAppError';
import DataFetchAlert from 'ui/shared/DataFetchAlert';
import BlobEntity from 'ui/shared/entities/blob/BlobEntity';
import PageTitle from 'ui/shared/Page/PageTitle';
......@@ -25,7 +26,7 @@ const BlobPageContent = () => {
const content = (() => {
if (isError) {
if (error?.status === 422 || error?.status === 404) {
if (isCustomAppError(error)) {
throwOnResourceLoadError({ resource: 'blob', error, isError: true });
}
......
......@@ -9,6 +9,7 @@ import throwOnResourceLoadError from 'lib/errors/throwOnResourceLoadError';
import getQueryParamString from 'lib/router/getQueryParamString';
import { publicClient } from 'lib/web3/client';
import TextAd from 'ui/shared/ad/TextAd';
import isCustomAppError from 'ui/shared/AppError/isCustomAppError';
import EntityTags from 'ui/shared/EntityTags';
import PageTitle from 'ui/shared/Page/PageTitle';
import RoutedTabs from 'ui/shared/Tabs/RoutedTabs';
......@@ -103,7 +104,7 @@ const TransactionPageContent = () => {
})();
if (isError && !showDegradedView) {
if (error?.status === 422 || error?.status === 404) {
if (isCustomAppError(error)) {
throwOnResourceLoadError({ resource: 'tx', error, isError: true });
}
}
......
......@@ -36,8 +36,8 @@ test('status code 500', async({ mount }) => {
await expect(component).toHaveScreenshot();
});
test('invalid tx hash', async({ mount }) => {
const error = { message: 'Invalid tx hash', cause: { status: 422, resource: 'tx' } } as Error;
test('tx not found', async({ mount }) => {
const error = { message: 'Not found', cause: { status: 404, resource: 'tx' } } as Error;
const component = await mount(
<TestApp>
<AppError error={ error }/>
......
......@@ -11,8 +11,8 @@ import getResourceErrorPayload from 'lib/errors/getResourceErrorPayload';
import AppErrorIcon from './AppErrorIcon';
import AppErrorTitle from './AppErrorTitle';
import AppErrorBlockConsensus from './custom/AppErrorBlockConsensus';
import AppErrorInvalidTxHash from './custom/AppErrorInvalidTxHash';
import AppErrorTooManyRequests from './custom/AppErrorTooManyRequests';
import AppErrorTxNotFound from './custom/AppErrorTxNotFound';
interface Props {
className?: string;
......@@ -47,11 +47,11 @@ const AppError = ({ error, className }: Props) => {
undefined;
const statusCode = getErrorCauseStatusCode(error) || getErrorObjStatusCode(error);
const isInvalidTxHash = cause && 'resource' in cause && cause.resource === 'tx' && statusCode === 422;
const isInvalidTxHash = cause && 'resource' in cause && cause.resource === 'tx' && statusCode === 404;
const isBlockConsensus = messageInPayload?.includes('Block lost consensus');
if (isInvalidTxHash) {
return <AppErrorInvalidTxHash/>;
return <AppErrorTxNotFound/>;
}
if (isBlockConsensus) {
......
/* eslint-disable max-len */
import { Box, OrderedList, ListItem, useColorModeValue, Flex } from '@chakra-ui/react';
import { Box, OrderedList, ListItem, useColorModeValue, Flex, chakra } from '@chakra-ui/react';
import React from 'react';
import IconSvg from 'ui/shared/IconSvg';
import AppErrorTitle from '../AppErrorTitle';
const AppErrorInvalidTxHash = () => {
const textColor = useColorModeValue('gray.500', 'gray.400');
const AppErrorTxNotFound = () => {
const snippet = {
borderColor: useColorModeValue('blackAlpha.300', 'whiteAlpha.300'),
iconBg: useColorModeValue('blackAlpha.800', 'whiteAlpha.800'),
......@@ -36,7 +35,7 @@ const AppErrorInvalidTxHash = () => {
</Flex>
</Box>
<AppErrorTitle title="Sorry, we are unable to locate this transaction hash"/>
<OrderedList color={ textColor } mt={ 3 } spacing={ 3 }>
<OrderedList mt={ 3 } spacing={ 3 }>
<ListItem>
If you have just submitted this transaction please wait for at least 30 seconds before refreshing this page.
</ListItem>
......@@ -47,11 +46,13 @@ const AppErrorInvalidTxHash = () => {
During times when the network is busy (i.e during ICOs) it can take a while for your transaction to propagate through the network and for us to index it.
</ListItem>
<ListItem>
If it still does not show up after 1 hour, please check with your sender/exchange/wallet/transaction provider for additional information.
<span>If it still does not show up after 1 hour, please check with your </span>
<chakra.span fontWeight={ 600 }>sender/exchange/wallet/transaction provider</chakra.span>
<span> for additional information.</span>
</ListItem>
</OrderedList>
</>
);
};
export default AppErrorInvalidTxHash;
export default AppErrorTxNotFound;
import type { ResourceError } from 'lib/api/resources';
// status codes when custom error screen should be shown
const CUSTOM_STATUS_CODES = [ 404, 422, 429 ];
export default function isCustomAppError(error: ResourceError<unknown>) {
return CUSTOM_STATUS_CODES.includes(error.status);
}
......@@ -7,12 +7,14 @@ import type { Transaction } from 'types/api/transaction';
import { SECOND } from 'lib/consts';
import dayjs from 'lib/date/dayjs';
import throwOnResourceLoadError from 'lib/errors/throwOnResourceLoadError';
import hexToDecimal from 'lib/hexToDecimal';
import { publicClient } from 'lib/web3/client';
import { GET_BLOCK, GET_TRANSACTION, GET_TRANSACTION_RECEIPT, GET_TRANSACTION_CONFIRMATIONS } from 'stubs/RPC';
import { unknownAddress } from 'ui/shared/address/utils';
import ServiceDegradationWarning from 'ui/shared/alerts/ServiceDegradationWarning';
import TestnetWarning from 'ui/shared/alerts/TestnetWarning';
import isCustomAppError from 'ui/shared/AppError/isCustomAppError';
import DataFetchAlert from 'ui/shared/DataFetchAlert';
import TxInfo from './details/TxInfo';
......@@ -141,8 +143,8 @@ const TxDetailsDegraded = ({ hash, txQuery }: Props) => {
}, [ txQuery.setRefetchOnError ]);
if (!query.data) {
if (originalError?.status === 404) {
throw Error('Not found', { cause: { status: 404 } as unknown as Error });
if (originalError && isCustomAppError(originalError)) {
throwOnResourceLoadError({ resource: 'tx', error: originalError, isError: true });
}
return <DataFetchAlert/>;
......
......@@ -10,6 +10,7 @@ import { route } from 'nextjs-routes';
import type { ResourceError } from 'lib/api/resources';
import throwOnResourceLoadError from 'lib/errors/throwOnResourceLoadError';
import isCustomAppError from 'ui/shared/AppError/isCustomAppError';
import CopyToClipboard from 'ui/shared/CopyToClipboard';
import DataFetchAlert from 'ui/shared/DataFetchAlert';
import DetailsInfoItem from 'ui/shared/DetailsInfoItem';
......@@ -42,7 +43,7 @@ const ZkEvmL2TxnBatchDetails = ({ query }: Props) => {
}, [ data, router ]);
if (isError) {
if (error?.status === 404 || error?.status === 422) {
if (isCustomAppError(error)) {
throwOnResourceLoadError({ isError, error });
}
......
......@@ -12,6 +12,7 @@ import { WEI, WEI_IN_GWEI } from 'lib/consts';
import throwOnResourceLoadError from 'lib/errors/throwOnResourceLoadError';
import { space } from 'lib/html-entities';
import { currencyUnits } from 'lib/units';
import isCustomAppError from 'ui/shared/AppError/isCustomAppError';
import CurrencyValue from 'ui/shared/CurrencyValue';
import DataFetchAlert from 'ui/shared/DataFetchAlert';
import DetailsInfoItem from 'ui/shared/DetailsInfoItem';
......@@ -48,7 +49,7 @@ const UserOpDetails = ({ query }: Props) => {
}, []);
if (isError) {
if (error?.status === 400 || error?.status === 404 || error?.status === 422) {
if (error?.status === 400 || isCustomAppError(error)) {
throwOnResourceLoadError({ isError, error });
}
......
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