Commit 324f675c authored by tom's avatar tom

better errors

parent ce6b8be1
......@@ -10,3 +10,6 @@ export const MINUTE = 60 * SECOND;
export const HOUR = 60 * MINUTE;
export const DAY = 24 * HOUR;
export const WEEK = 7 * DAY;
export const Kb = 1_000;
export const Mb = 1_000 * Kb;
......@@ -35,10 +35,13 @@ function MyApp({ Component, pageProps }: AppProps) {
},
}));
const renderErrorScreen = React.useCallback(() => {
const renderErrorScreen = React.useCallback((error?: Error) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const statusCode = (error?.cause as any)?.status || 500;
return (
<AppError
statusCode={ 500 }
statusCode={ statusCode }
height="100vh"
display="flex"
flexDirection="column"
......
......@@ -129,7 +129,7 @@ const ContractCode = () => {
<AddressLink type="address" hash={ data.verified_twin_address_hash } truncation="constant" ml={ 2 }/>
</Address>
<chakra.span mt={ 1 }>All functions displayed below are from ABI of that contract. In order to verify current contract, proceed with </chakra.span>
<LinkInternal href={ link('address_contract_verification', { id: data.verified_twin_address_hash }) }>Verify & Publish</LinkInternal>
<LinkInternal href={ link('address_contract_verification', { id: addressHash }) }>Verify & Publish</LinkInternal>
<span> page</span>
</Alert>
) }
......
......@@ -76,9 +76,6 @@ const ContractVerificationForm = ({ method: methodFromQuery, config, hash }: Pro
}, [ apiFetch, hash ]);
const handleNewSocketMessage: SocketMessage.ContractVerification['handler'] = React.useCallback((payload) => {
// eslint-disable-next-line no-console
console.log('__>__ handleNewSocketMessage', payload);
if (payload.status === 'error') {
const errors = formatSocketErrors(payload.errors);
errors.forEach(([ field, error ]) => setError(field, error));
......@@ -100,6 +97,10 @@ const ContractVerificationForm = ({ method: methodFromQuery, config, hash }: Pro
}, [ hash, router, setError, toast ]);
const handleSocketError = React.useCallback(() => {
if (!formState.isSubmitting) {
return;
}
submitPromiseResolver.current?.(null);
const toastId = 'socket-error';
......@@ -112,13 +113,13 @@ const ContractVerificationForm = ({ method: methodFromQuery, config, hash }: Pro
variant: 'subtle',
isClosable: true,
});
}, [ toast ]);
}, [ formState.isSubmitting, toast ]);
const channel = useSocketChannel({
topic: `addresses:${ hash.toLowerCase() }`,
onSocketClose: handleSocketError,
onSocketError: handleSocketError,
isDisabled: !formState.isSubmitting,
isDisabled: false,
});
useSocketMessage({
channel,
......
......@@ -5,6 +5,7 @@ import { Controller, useFormContext } from 'react-hook-form';
import type { FormFields } from '../types';
import { Mb } from 'lib/consts';
import DragAndDropArea from 'ui/shared/forms/DragAndDropArea';
import FieldError from 'ui/shared/forms/FieldError';
import FileInput from 'ui/shared/forms/FileInput';
......@@ -45,7 +46,7 @@ const ContractVerificationFieldSources = ({ fileTypes, multiple, title, classNam
const errorList = fileError?.message?.split(';');
return (
<Box display="grid" gridTemplateColumns={{ base: '1fr', lg: '1fr 1fr' }} columnGap={ 3 } rowGap={ 3 }>
<Box display="grid" gridTemplateColumns={{ base: 'minmax(0, 1fr)', lg: 'minmax(0, 1fr) minmax(0, 1fr)' }} columnGap={ 3 } rowGap={ 3 }>
{ files.map((file, index) => (
<Box key={ file.name + file.lastModified + index }>
<FileSnippet
......@@ -92,7 +93,8 @@ const ContractVerificationFieldSources = ({ fileTypes, multiple, title, classNam
const validateFileType = React.useCallback(async(value: FieldPathValue<FormFields, 'sources'>): Promise<ValidateResult> => {
if (Array.isArray(value)) {
const errors = value.map(({ name }) => fileTypes.some((ext) => name.endsWith(ext)) ? '' : 'Wrong file type');
const errorText = `Wrong file type. Allowed files types are ${ fileTypes.join(',') }.`;
const errors = value.map(({ name }) => fileTypes.some((ext) => name.endsWith(ext)) ? '' : errorText);
if (errors.some((item) => item !== '')) {
return errors.join(';');
}
......@@ -102,8 +104,8 @@ const ContractVerificationFieldSources = ({ fileTypes, multiple, title, classNam
const validateFileSize = React.useCallback(async(value: FieldPathValue<FormFields, 'sources'>): Promise<ValidateResult> => {
if (Array.isArray(value)) {
const FILE_SIZE_LIMIT = 260;
const errors = value.map(({ size }) => size > FILE_SIZE_LIMIT ? 'File is too big' : '');
const FILE_SIZE_LIMIT = 20 * Mb;
const errors = value.map(({ size }) => size > FILE_SIZE_LIMIT ? 'File is too big. Maximum size is 20 Mb.' : '');
if (errors.some((item) => item !== '')) {
return errors.join(';');
}
......
......@@ -3,7 +3,7 @@ import React from 'react';
import ContractVerificationMethod from '../ContractVerificationMethod';
import ContractVerificationFieldSources from '../fields/ContractVerificationFieldSources';
const FILE_TYPES = [ '.json' as const ];
const FILE_TYPES = [ '.json' as const, '.sol' as const ];
const ContractVerificationSourcify = () => {
return (
......
......@@ -29,6 +29,17 @@ const ContractVerification = () => {
const hash = router.query.id?.toString();
const method = router.query.id?.toString() as SmartContractVerificationMethod | undefined;
const contractQuery = useApiQuery('contract', {
pathParams: { id: hash },
queryOptions: {
enabled: Boolean(hash),
},
});
if (contractQuery.isError && contractQuery.error.status === 404) {
throw Error('Not found', { cause: contractQuery.error as unknown as Error });
}
const configQuery = useApiQuery('contract_verification_config', {
queryOptions: {
select: (data: unknown) => {
......@@ -50,12 +61,20 @@ const ContractVerification = () => {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ ]);
const isVerifiedContract = contractQuery.data?.is_verified;
React.useEffect(() => {
if (isVerifiedContract) {
router.push(link('address_index', { id: hash }, { tab: 'contract' }), undefined, { scroll: false, shallow: true });
}
}, [ hash, isVerifiedContract, router ]);
const content = (() => {
if (configQuery.isError || !hash) {
if (configQuery.isError || !hash || contractQuery.isError) {
return <DataFetchAlert/>;
}
if (configQuery.isLoading) {
if (configQuery.isLoading || contractQuery.isLoading || isVerifiedContract) {
return <ContentLoader/>;
}
......
......@@ -35,7 +35,7 @@ const Page = ({
return <PageContent isHomePage={ isHomePage }>{ content }</PageContent>;
}
return isInvalidTxHash ? <ErrorInvalidTxHash/> : <AppError statusCode={ 500 }/>;
return isInvalidTxHash ? <ErrorInvalidTxHash/> : <AppError statusCode={ statusCode }/>;
}, [ isHomePage, wrapChildren ]);
const renderedChildren = wrapChildren ? (
......
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