diff --git a/src/app/components/ErrorDisplay/index.tsx b/src/app/components/ErrorDisplay/index.tsx index 56443f9e67..3dce563590 100644 --- a/src/app/components/ErrorDisplay/index.tsx +++ b/src/app/components/ErrorDisplay/index.tsx @@ -11,6 +11,10 @@ type FormattedError = { title: string; message: ReactNode } const errorMap: Record FormattedError> = { [AppErrors.Unknown]: (t, error) => ({ title: t('errors.unknown'), message: error.message }), [AppErrors.InvalidAddress]: t => ({ title: t('errors.invalidAddress'), message: t('errors.validateURL') }), + [AppErrors.CannotLoadData]: t => ({ + title: t('errors.canNotLoadData'), + message: t('errors.canNotReachDataSource'), + }), [AppErrors.InvalidBlockHeight]: t => ({ title: t('errors.invalidBlockHeight'), message: t('errors.validateURL'), @@ -44,6 +48,10 @@ const errorMap: Record Formatt title: t('errors.notFoundBlockHeight'), message: t('errors.validateURL'), }), + [AppErrors.NotFoundTokenAddress]: t => ({ + title: t('errors.notFoundToken'), + message: t('errors.validateURL'), + }), [AppErrors.NotFoundTxHash]: t => ({ title: t('errors.notFoundTx'), message: t('errors.validateURL') }), [AppErrors.InvalidUrl]: t => ({ title: t('errors.invalidUrl'), message: t('errors.validateURL') }), [AppErrors.UnsupportedLayer]: t => ({ diff --git a/src/app/pages/AccountDetailsPage/AccountDetailsCard.tsx b/src/app/pages/AccountDetailsPage/AccountDetailsCard.tsx index a5611f4b40..f60caf565a 100644 --- a/src/app/pages/AccountDetailsPage/AccountDetailsCard.tsx +++ b/src/app/pages/AccountDetailsPage/AccountDetailsCard.tsx @@ -8,6 +8,7 @@ import { TokenPriceInfo } from '../../../coin-gecko/api' type AccountDetailsProps = { isLoading: boolean isError: boolean + errorCode: any isContract: boolean account: RuntimeAccount | undefined token: EvmToken | undefined @@ -17,6 +18,7 @@ type AccountDetailsProps = { export const AccountDetailsCard: FC = ({ isLoading, isError, + errorCode, isContract, account, token, @@ -32,6 +34,7 @@ export const AccountDetailsCard: FC = ({ = ({ isLoading, isError, account, token, tokenPriceInfo, showLayer }) => { +}> = ({ isLoading, isError, errorCode, account, token, tokenPriceInfo, showLayer }) => { const { t } = useTranslation() - return isError ? ( - - ) : ( + if (isError) { + switch (errorCode) { + case 'ERR_NETWORK': + return + default: + // TODO: what other error cases do we have? + console.log('Error code is', errorCode) + } + } + return ( { const query = useGetRuntimeAccountsAddress(network, layer, address) const account = query.data?.data - const { isLoading, isError, isFetched } = query + const { isLoading, isError, isFetched, error } = query - return { account, isLoading, isError, isFetched } + const errorCode = (error as any)?.code + + return { account, isLoading, isError, errorCode, isFetched } } export const useAccountTransactions = (scope: SearchScope, address: string) => { diff --git a/src/app/pages/AccountDetailsPage/index.tsx b/src/app/pages/AccountDetailsPage/index.tsx index c7e6f58974..8bf1da2d1f 100644 --- a/src/app/pages/AccountDetailsPage/index.tsx +++ b/src/app/pages/AccountDetailsPage/index.tsx @@ -33,7 +33,7 @@ export const AccountDetailsPage: FC = () => { const scope = useRequiredScopeParam() const address = useLoaderData() as string - const { account, isLoading: isAccountLoading, isError } = useAccount(scope, address) + const { account, isLoading: isAccountLoading, isError, errorCode } = useAccount(scope, address) const isContract = !!account?.evm_contract const { token, isLoading: isTokenLoading } = useTokenInfo(scope, address, isContract) @@ -63,6 +63,7 @@ export const AccountDetailsPage: FC = () => { { // We should use useGetConsensusBlocksHeight() } const blockHeight = parseInt(useParams().blockHeight!, 10) - const { isLoading, data } = useGetRuntimeBlockByHeight( + const { isLoading, data, error } = useGetRuntimeBlockByHeight( scope.network, scope.layer, // This is OK, since consensus is already handled separately blockHeight, ) - if (!data && !isLoading) { + + if (!data?.data && !isLoading) { + const errorCode = (error as any)?.code + switch (errorCode) { + case 'ERR_NETWORK': + throw AppErrors.CannotLoadData + default: + // TODO: look for other error codes, too. + // (Currently we are not aware of anything else) + } throw AppErrors.NotFoundBlockHeight } const block = data?.data diff --git a/src/app/pages/SearchResultsPage/SearchResultsList.tsx b/src/app/pages/SearchResultsPage/SearchResultsList.tsx index 8079f8fc5c..8c14460eb0 100644 --- a/src/app/pages/SearchResultsPage/SearchResultsList.tsx +++ b/src/app/pages/SearchResultsPage/SearchResultsList.tsx @@ -82,6 +82,7 @@ export const SearchResultsList: FC<{ { const scope = useRequiredScopeParam() const address = useLoaderData() as string - const { token, isError } = useTokenInfo(scope, address) + const { token, isError, errorCode } = useTokenInfo(scope, address) if (isError) { - throw AppErrors.InvalidAddress + switch (errorCode) { + case 'ERR_NETWORK': + throw AppErrors.CannotLoadData + case 'ERR_BAD_REQUEST': + throw AppErrors.NotFoundTokenAddress + default: + // TODO: look for other error codes, too + // (Currently we are not aware of anything else.) + console.log('Error code is', errorCode) + throw AppErrors.NotFoundTokenAddress + } } const tokenTransfersLink = useHref(``) diff --git a/src/app/pages/TransactionDetailPage/index.tsx b/src/app/pages/TransactionDetailPage/index.tsx index 04db48c211..f179429919 100644 --- a/src/app/pages/TransactionDetailPage/index.tsx +++ b/src/app/pages/TransactionDetailPage/index.tsx @@ -92,7 +92,7 @@ export const TransactionDetailPage: FC = () => { AddressSwitchOption.Oasis | AddressSwitchOption.ETH >(AddressSwitchOption.ETH) - const { isLoading, data } = useGetRuntimeTransactionsTxHash( + const { isLoading, data, error } = useGetRuntimeTransactionsTxHash( scope.network, scope.layer, // This is OK since consensus has been handled separately hash, @@ -105,7 +105,16 @@ export const TransactionDetailPage: FC = () => { const tokenPriceInfo = useTokenPrice(getTickerForNetwork(scope.network)) if (!transaction && !isLoading) { - throw AppErrors.NotFoundTxHash + const errorCode = (error as any)?.code + switch (errorCode) { + case 'ERR_NETWORK': + throw AppErrors.CannotLoadData + default: + // TODO: what other error codes are there? + // (We are not aware of anything else) + console.log('Error code is', errorCode) + throw AppErrors.NotFoundTxHash + } } return ( diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index 7148067c33..ffd73627f2 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -152,6 +152,8 @@ "value": "{{value, number}}" }, "errors": { + "canNotLoadData": "Can not load data", + "canNotReachDataSource": "We were unable to reach the data source to request this data. This is probably a temporary (network?) problem. Please try again later.", "code": "error code", "error": "Error", "loadFirstPage": "load the first page", @@ -163,6 +165,7 @@ "invalidPageNumber": "Invalid page number", "invalidTxHash": "Invalid transaction hash", "notFoundBlockHeight": "Block not found", + "notFoundToken": "Token not found", "notFoundTx": "Transaction not found", "pageDoesNotExist": "The page you are looking for does not exist.", "validateURL": "Please validate provided URL", diff --git a/src/oasis-nexus/api.ts b/src/oasis-nexus/api.ts index fce22e79f0..7b3f7a92fe 100644 --- a/src/oasis-nexus/api.ts +++ b/src/oasis-nexus/api.ts @@ -492,13 +492,7 @@ export function useGetRuntimeBlockByHeight( if (status !== 200) return data const block = data.blocks[0] if (!block || block.round !== blockHeight) { - throw new axios.AxiosError('not found', 'ERR_BAD_REQUEST', this, null, { - status: 404, - statusText: 'not found', - config: this, - data: 'not found', - headers: {}, - }) + return undefined } return { ...block, diff --git a/src/types/errors.ts b/src/types/errors.ts index 00e7ffc21a..27b8a7c9fe 100644 --- a/src/types/errors.ts +++ b/src/types/errors.ts @@ -19,8 +19,10 @@ export enum AppErrors { PageDoesNotExist = 'page_does_not_exist', NotFoundBlockHeight = 'not_found_block_height', NotFoundTxHash = 'not_found_tx_hash', + NotFoundTokenAddress = 'not_found_token_address', InvalidUrl = 'invalid_url', Storage = 'storage', + CannotLoadData = 'cannot_load_data', } export interface ErrorPayload {