diff --git a/ui/address/AddressDetails.tsx b/ui/address/AddressDetails.tsx index 1554ee726f..662fd86a70 100644 --- a/ui/address/AddressDetails.tsx +++ b/ui/address/AddressDetails.tsx @@ -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 ; + // 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 ; + } } const data = addressQuery.isError ? error404Data : addressQuery.data; diff --git a/ui/pages/Blob.tsx b/ui/pages/Blob.tsx index 007ff7f435..4df70d1ba9 100644 --- a/ui/pages/Blob.tsx +++ b/ui/pages/Blob.tsx @@ -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 }); } diff --git a/ui/pages/Transaction.tsx b/ui/pages/Transaction.tsx index 74853da4ee..07ccc1d687 100644 --- a/ui/pages/Transaction.tsx +++ b/ui/pages/Transaction.tsx @@ -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 }); } } diff --git a/ui/shared/AppError/AppError.pw.tsx b/ui/shared/AppError/AppError.pw.tsx index a3405e2b99..36f23b03f3 100644 --- a/ui/shared/AppError/AppError.pw.tsx +++ b/ui/shared/AppError/AppError.pw.tsx @@ -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( diff --git a/ui/shared/AppError/AppError.tsx b/ui/shared/AppError/AppError.tsx index b5199d5e5b..e3a0a16aff 100644 --- a/ui/shared/AppError/AppError.tsx +++ b/ui/shared/AppError/AppError.tsx @@ -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 ; + return ; } if (isBlockConsensus) { diff --git a/ui/shared/AppError/__screenshots__/AppError.pw.tsx_default_invalid-tx-hash-1.png b/ui/shared/AppError/__screenshots__/AppError.pw.tsx_default_invalid-tx-hash-1.png deleted file mode 100644 index b06fb92cb9..0000000000 Binary files a/ui/shared/AppError/__screenshots__/AppError.pw.tsx_default_invalid-tx-hash-1.png and /dev/null differ diff --git a/ui/shared/AppError/__screenshots__/AppError.pw.tsx_default_tx-not-found-1.png b/ui/shared/AppError/__screenshots__/AppError.pw.tsx_default_tx-not-found-1.png new file mode 100644 index 0000000000..ba19d9d787 Binary files /dev/null and b/ui/shared/AppError/__screenshots__/AppError.pw.tsx_default_tx-not-found-1.png differ diff --git a/ui/shared/AppError/custom/AppErrorInvalidTxHash.tsx b/ui/shared/AppError/custom/AppErrorTxNotFound.tsx similarity index 83% rename from ui/shared/AppError/custom/AppErrorInvalidTxHash.tsx rename to ui/shared/AppError/custom/AppErrorTxNotFound.tsx index a6da98596f..6686f43582 100644 --- a/ui/shared/AppError/custom/AppErrorInvalidTxHash.tsx +++ b/ui/shared/AppError/custom/AppErrorTxNotFound.tsx @@ -1,13 +1,12 @@ /* 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 = () => { - + If you have just submitted this transaction please wait for at least 30 seconds before refreshing this page. @@ -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. - If it still does not show up after 1 hour, please check with your sender/exchange/wallet/transaction provider for additional information. + If it still does not show up after 1 hour, please check with your + sender/exchange/wallet/transaction provider + for additional information. ); }; -export default AppErrorInvalidTxHash; +export default AppErrorTxNotFound; diff --git a/ui/shared/AppError/isCustomAppError.ts b/ui/shared/AppError/isCustomAppError.ts new file mode 100644 index 0000000000..328368e2ae --- /dev/null +++ b/ui/shared/AppError/isCustomAppError.ts @@ -0,0 +1,8 @@ +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) { + return CUSTOM_STATUS_CODES.includes(error.status); +} diff --git a/ui/tx/TxDetailsDegraded.tsx b/ui/tx/TxDetailsDegraded.tsx index d67441350c..e1bace40d9 100644 --- a/ui/tx/TxDetailsDegraded.tsx +++ b/ui/tx/TxDetailsDegraded.tsx @@ -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 ; diff --git a/ui/txnBatches/zkEvmL2/ZkEvmL2TxnBatchDetails.tsx b/ui/txnBatches/zkEvmL2/ZkEvmL2TxnBatchDetails.tsx index 234a178ccb..950a2ccec7 100644 --- a/ui/txnBatches/zkEvmL2/ZkEvmL2TxnBatchDetails.tsx +++ b/ui/txnBatches/zkEvmL2/ZkEvmL2TxnBatchDetails.tsx @@ -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 }); } diff --git a/ui/userOp/UserOpDetails.tsx b/ui/userOp/UserOpDetails.tsx index 461e403b7c..9d06807485 100644 --- a/ui/userOp/UserOpDetails.tsx +++ b/ui/userOp/UserOpDetails.tsx @@ -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 }); }