From 9fe4a38e45f010d5416e2ef6f521883cd6f2833a Mon Sep 17 00:00:00 2001 From: lukaw3d Date: Thu, 8 Aug 2024 20:10:04 +0200 Subject: [PATCH 1/3] Automatically throw on 5xx error responses --- .changelog/1493.bugfix.md | 1 + src/index.tsx | 5 +++++ 2 files changed, 6 insertions(+) create mode 100644 .changelog/1493.bugfix.md diff --git a/.changelog/1493.bugfix.md b/.changelog/1493.bugfix.md new file mode 100644 index 000000000..58eb99eee --- /dev/null +++ b/.changelog/1493.bugfix.md @@ -0,0 +1 @@ +Automatically throw on 5xx error responses diff --git a/src/index.tsx b/src/index.tsx index 09a03017d..bce9b1e01 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -14,6 +14,11 @@ const queryClient = new QueryClient({ queries: { refetchOnWindowFocus: false, retry: false, + useErrorBoundary: (error: any) => { + // Automatically throw on 5xx errors. Components that want to handle + // errors should set `useErrorBoundary: false` in their queries. + return error.response?.status >= 500 + }, }, }, }) From bc66fc4d7230b9416527d40da54f8c5d66d94c28 Mon Sep 17 00:00:00 2001 From: lukaw3d Date: Thu, 8 Aug 2024 20:10:58 +0200 Subject: [PATCH 2/3] Don't automatically throw on API status, gecko, and account names --- src/app/components/OfflineBanner/hook.ts | 6 +++--- src/app/data/oasis-account-names.ts | 7 ++++--- src/app/data/pontusx-account-names.ts | 10 +++++++--- src/coin-gecko/api.ts | 1 + 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/app/components/OfflineBanner/hook.ts b/src/app/components/OfflineBanner/hook.ts index 5a3c37453..5f5f3f28a 100644 --- a/src/app/components/OfflineBanner/hook.ts +++ b/src/app/components/OfflineBanner/hook.ts @@ -15,7 +15,7 @@ import { UseQueryResult } from '@tanstack/react-query' export const useIsApiReachable = ( network: Network, ): { reachable: true } | { reachable: false; reason: 'userOffline' | 'apiOffline' } => { - const query = useGetStatus(network) + const query = useGetStatus(network, { query: { useErrorBoundary: false } }) if (query.isPaused) return { reachable: false, reason: 'userOffline' } if (query.isFetched && !query.isSuccess) return { reachable: false, reason: 'apiOffline' } return { reachable: true } @@ -80,7 +80,7 @@ export const useConsensusFreshness = ( queryParams: { polling?: boolean } = {}, ): FreshnessInfo => { const query = useGetStatus(network, { - query: { refetchInterval: queryParams.polling ? 8000 : undefined }, + query: { refetchInterval: queryParams.polling ? 8000 : undefined, useErrorBoundary: false }, }) return useFreshness(network, query) @@ -95,7 +95,7 @@ export const useRuntimeFreshness = ( } const query = useGetRuntimeStatus(scope.network, scope.layer, { - query: { refetchInterval: queryParams.polling ? 8000 : undefined }, + query: { refetchInterval: queryParams.polling ? 8000 : undefined, useErrorBoundary: false }, }) return useFreshness(scope.network, query) diff --git a/src/app/data/oasis-account-names.ts b/src/app/data/oasis-account-names.ts index 099d5f3d5..c3436b9b0 100644 --- a/src/app/data/oasis-account-names.ts +++ b/src/app/data/oasis-account-names.ts @@ -65,11 +65,12 @@ const getOasisAccountsMetadata = async (network: Network, layer: Layer): Promise export const useOasisAccountsMetadata = ( network: Network, layer: Layer, - queryOptions: { enabled: boolean }, + queryOptions: { enabled: boolean; useErrorBoundary?: boolean }, ) => { return useQuery(['oasisAccounts', network, layer], () => getOasisAccountsMetadata(network, layer), { enabled: queryOptions.enabled, staleTime: Infinity, + useErrorBoundary: queryOptions.useErrorBoundary, }) } @@ -77,7 +78,7 @@ export const useOasisAccountMetadata = ( network: Network, layer: Layer, address: string, - queryOptions: { enabled: boolean }, + queryOptions: { enabled: boolean; useErrorBoundary?: boolean }, ): AccountMetadataInfo => { const { isLoading, isError, error, data: allData } = useOasisAccountsMetadata(network, layer, queryOptions) if (isError) { @@ -101,7 +102,7 @@ export const useSearchForOasisAccountsByName = ( isError: isMetadataError, error: metadataError, data: namedAccounts, - } = useOasisAccountsMetadata(network, layer, queryOptions) + } = useOasisAccountsMetadata(network, layer, { ...queryOptions, useErrorBoundary: false }) if (isMetadataError) { console.log('Failed to load Oasis account metadata', metadataError) } diff --git a/src/app/data/pontusx-account-names.ts b/src/app/data/pontusx-account-names.ts index 2e5e59a8e..be08fd988 100644 --- a/src/app/data/pontusx-account-names.ts +++ b/src/app/data/pontusx-account-names.ts @@ -34,16 +34,20 @@ const getPontusXAccountsMetadata = async () => { } } -export const usePontusXAccountsMetadata = (queryOptions: { enabled: boolean }) => { +export const usePontusXAccountsMetadata = (queryOptions: { + enabled: boolean + useErrorBoundary?: boolean +}) => { return useQuery(['pontusXNames'], getPontusXAccountsMetadata, { enabled: queryOptions.enabled, staleTime: Infinity, + useErrorBoundary: queryOptions.useErrorBoundary, }) } export const usePontusXAccountMetadata = ( address: string, - queryOptions: { enabled: boolean }, + queryOptions: { enabled: boolean; useErrorBoundary?: boolean }, ): AccountMetadataInfo => { const { isLoading, isError, error, data: allData } = usePontusXAccountsMetadata(queryOptions) if (isError) { @@ -66,7 +70,7 @@ export const useSearchForPontusXAccountsByName = ( isError: isMetadataError, error: metadataError, data: namedAccounts, - } = usePontusXAccountsMetadata(queryOptions) + } = usePontusXAccountsMetadata({ ...queryOptions, useErrorBoundary: false }) if (isMetadataError) { console.log('Failed to load Pontus-X account names', metadataError) } diff --git a/src/coin-gecko/api.ts b/src/coin-gecko/api.ts index e50f1cf1d..c0c278baf 100644 --- a/src/coin-gecko/api.ts +++ b/src/coin-gecko/api.ts @@ -43,6 +43,7 @@ export function useGetTokenPricesFromGecko(tokenIds: string[], fiatCurrency: str }), { staleTime, + useErrorBoundary: false, }, ) } From 92c9bcebfb6478d791962efc6ef7bedbca6091e8 Mon Sep 17 00:00:00 2001 From: lukaw3d Date: Fri, 9 Aug 2024 20:54:44 +0200 Subject: [PATCH 3/3] Refactor queryOptions type in wrappers --- src/app/data/oasis-account-names.ts | 13 ++++++------ src/app/data/pontusx-account-names.ts | 30 +++++++++++++++++---------- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/src/app/data/oasis-account-names.ts b/src/app/data/oasis-account-names.ts index c3436b9b0..00200a308 100644 --- a/src/app/data/oasis-account-names.ts +++ b/src/app/data/oasis-account-names.ts @@ -1,5 +1,5 @@ import axios from 'axios' -import { useQuery } from '@tanstack/react-query' +import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { Layer, useGetConsensusAccountsAddresses, @@ -65,12 +65,11 @@ const getOasisAccountsMetadata = async (network: Network, layer: Layer): Promise export const useOasisAccountsMetadata = ( network: Network, layer: Layer, - queryOptions: { enabled: boolean; useErrorBoundary?: boolean }, + queryOptions: UseQueryOptions, ) => { return useQuery(['oasisAccounts', network, layer], () => getOasisAccountsMetadata(network, layer), { - enabled: queryOptions.enabled, staleTime: Infinity, - useErrorBoundary: queryOptions.useErrorBoundary, + ...queryOptions, }) } @@ -78,7 +77,7 @@ export const useOasisAccountMetadata = ( network: Network, layer: Layer, address: string, - queryOptions: { enabled: boolean; useErrorBoundary?: boolean }, + queryOptions: UseQueryOptions, ): AccountMetadataInfo => { const { isLoading, isError, error, data: allData } = useOasisAccountsMetadata(network, layer, queryOptions) if (isError) { @@ -95,14 +94,14 @@ export const useSearchForOasisAccountsByName = ( network: Network, layer: Layer, nameFragment: string, - queryOptions: { enabled: boolean }, + queryOptions: { enabled: boolean } & UseQueryOptions, ): AccountNameSearchResults => { const { isLoading: isMetadataLoading, isError: isMetadataError, error: metadataError, data: namedAccounts, - } = useOasisAccountsMetadata(network, layer, { ...queryOptions, useErrorBoundary: false }) + } = useOasisAccountsMetadata(network, layer, { useErrorBoundary: false, ...queryOptions }) if (isMetadataError) { console.log('Failed to load Oasis account metadata', metadataError) } diff --git a/src/app/data/pontusx-account-names.ts b/src/app/data/pontusx-account-names.ts index be08fd988..a17732a28 100644 --- a/src/app/data/pontusx-account-names.ts +++ b/src/app/data/pontusx-account-names.ts @@ -1,5 +1,5 @@ import axios from 'axios' -import { useQuery } from '@tanstack/react-query' +import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { AccountMetadata, AccountMap, @@ -14,7 +14,12 @@ import { getOasisAddress } from '../utils/helpers' const DATA_SOURCE_URL = 'https://raw.githubusercontent.com/deltaDAO/mvg-portal/main/pontusxAddresses.json' -const getPontusXAccountsMetadata = async () => { +type PontusXAccountsMetadata = { + map: AccountMap + list: AccountMetadata[] +} + +const getPontusXAccountsMetadata = async (): Promise => { const response = await axios.get(DATA_SOURCE_URL) if (response.status !== 200) throw new Error("Couldn't load names") if (!response.data) throw new Error("Couldn't load names") @@ -34,20 +39,18 @@ const getPontusXAccountsMetadata = async () => { } } -export const usePontusXAccountsMetadata = (queryOptions: { - enabled: boolean - useErrorBoundary?: boolean -}) => { +export const usePontusXAccountsMetadata = ( + queryOptions: UseQueryOptions, +) => { return useQuery(['pontusXNames'], getPontusXAccountsMetadata, { - enabled: queryOptions.enabled, staleTime: Infinity, - useErrorBoundary: queryOptions.useErrorBoundary, + ...queryOptions, }) } export const usePontusXAccountMetadata = ( address: string, - queryOptions: { enabled: boolean; useErrorBoundary?: boolean }, + queryOptions: UseQueryOptions, ): AccountMetadataInfo => { const { isLoading, isError, error, data: allData } = usePontusXAccountsMetadata(queryOptions) if (isError) { @@ -63,14 +66,19 @@ export const usePontusXAccountMetadata = ( export const useSearchForPontusXAccountsByName = ( network: Network, nameFragment: string, - queryOptions: { enabled: boolean }, + queryOptions: { enabled: boolean } & UseQueryOptions< + PontusXAccountsMetadata, + unknown, + PontusXAccountsMetadata, + string[] + >, ): AccountNameSearchRuntimeResults => { const { isLoading: isMetadataLoading, isError: isMetadataError, error: metadataError, data: namedAccounts, - } = usePontusXAccountsMetadata({ ...queryOptions, useErrorBoundary: false }) + } = usePontusXAccountsMetadata({ useErrorBoundary: false, ...queryOptions }) if (isMetadataError) { console.log('Failed to load Pontus-X account names', metadataError) }