Commit 7c00d780 authored by tom's avatar tom

form config

parent 988d3f6f
...@@ -17,7 +17,7 @@ import type { ...@@ -17,7 +17,7 @@ import type {
import type { AddressesResponse } from 'types/api/addresses'; import type { AddressesResponse } from 'types/api/addresses';
import type { BlocksResponse, BlockTransactionsResponse, Block, BlockFilters } from 'types/api/block'; import type { BlocksResponse, BlockTransactionsResponse, Block, BlockFilters } from 'types/api/block';
import type { ChartMarketResponse, ChartTransactionResponse } from 'types/api/charts'; import type { ChartMarketResponse, ChartTransactionResponse } from 'types/api/charts';
import type { SmartContract, SmartContractReadMethod, SmartContractWriteMethod } from 'types/api/contract'; import type { SmartContract, SmartContractReadMethod, SmartContractWriteMethod, SmartContractVerificationConfig } from 'types/api/contract';
import type { IndexingStatus } from 'types/api/indexingStatus'; import type { IndexingStatus } from 'types/api/indexingStatus';
import type { InternalTransactionsResponse } from 'types/api/internalTransaction'; import type { InternalTransactionsResponse } from 'types/api/internalTransaction';
import type { LogsResponseTx, LogsResponseAddress } from 'types/api/log'; import type { LogsResponseTx, LogsResponseAddress } from 'types/api/log';
...@@ -204,6 +204,9 @@ export const RESOURCES = { ...@@ -204,6 +204,9 @@ export const RESOURCES = {
contract_methods_write_proxy: { contract_methods_write_proxy: {
path: '/api/v2/smart-contracts/:id/methods-write-proxy', path: '/api/v2/smart-contracts/:id/methods-write-proxy',
}, },
contract_verification_config: {
path: '/api/v2/smart-contracts/verification/config',
},
// TOKEN // TOKEN
token: { token: {
...@@ -356,6 +359,7 @@ Q extends 'contract_methods_read' ? Array<SmartContractReadMethod> : ...@@ -356,6 +359,7 @@ Q extends 'contract_methods_read' ? Array<SmartContractReadMethod> :
Q extends 'contract_methods_read_proxy' ? Array<SmartContractReadMethod> : Q extends 'contract_methods_read_proxy' ? Array<SmartContractReadMethod> :
Q extends 'contract_methods_write' ? Array<SmartContractWriteMethod> : Q extends 'contract_methods_write' ? Array<SmartContractWriteMethod> :
Q extends 'contract_methods_write_proxy' ? Array<SmartContractWriteMethod> : Q extends 'contract_methods_write_proxy' ? Array<SmartContractWriteMethod> :
Q extends 'contract_verification_config' ? SmartContractVerificationConfig :
never; never;
/* eslint-enable @typescript-eslint/indent */ /* eslint-enable @typescript-eslint/indent */
......
...@@ -113,3 +113,19 @@ export interface SmartContractQueryMethodReadError { ...@@ -113,3 +113,19 @@ export interface SmartContractQueryMethodReadError {
} }
export type SmartContractQueryMethodRead = SmartContractQueryMethodReadSuccess | SmartContractQueryMethodReadError; export type SmartContractQueryMethodRead = SmartContractQueryMethodReadSuccess | SmartContractQueryMethodReadError;
// VERIFICATION
export type SmartContractVerificationMethod = 'flattened_code' | 'standard_input' | 'sourcify' | 'multi_part' | 'vyper_multi_part';
export interface SmartContractVerificationConfigRaw {
solidity_compiler_versions: Array<string>;
solidity_evm_versions: Array<string>;
verification_options: Array<string>;
vyper_compiler_versions: Array<string>;
vyper_evm_versions: Array<string>;
}
export interface SmartContractVerificationConfig extends SmartContractVerificationConfigRaw {
verification_options: Array<SmartContractVerificationMethod>;
}
import { test, expect } from '@playwright/experimental-ct-react'; import { test, expect } from '@playwright/experimental-ct-react';
import React from 'react'; import React from 'react';
import type { SmartContractVerificationConfig } from 'types/api/contract';
import TestApp from 'playwright/TestApp'; import TestApp from 'playwright/TestApp';
import ContractVerificationForm from './ContractVerificationForm'; import ContractVerificationForm from './ContractVerificationForm';
...@@ -11,10 +13,48 @@ const hooksConfig = { ...@@ -11,10 +13,48 @@ const hooksConfig = {
}, },
}; };
const formConfig: SmartContractVerificationConfig = {
solidity_compiler_versions: [
'v0.8.17+commit.8df45f5f',
'v0.8.16+commit.07a7930e',
'v0.8.15+commit.e14f2714',
'v0.8.18-nightly.2022.11.23+commit.eb2f874e',
'v0.8.17-nightly.2022.8.24+commit.22a0c46e',
'v0.8.16-nightly.2022.7.6+commit.b6f11b33',
],
solidity_evm_versions: [
'default',
'london',
'berlin',
],
verification_options: [
'flattened_code',
'standard_input',
'sourcify',
'multi_part',
'vyper_multi_part',
],
vyper_compiler_versions: [
'v0.3.7+commit.6020b8bb',
'v0.3.1+commit.0463ea4c',
'v0.3.0+commit.8a23feb',
'v0.2.16+commit.59e1bdd',
'v0.2.3+commit.006968f',
'v0.2.2+commit.337c2ef',
'v0.1.0-beta.17+commit.0671b7b',
],
vyper_evm_versions: [
'byzantium',
'constantinople',
'petersburg',
'istanbul',
],
};
test('flatten source code method +@dark-mode +@mobile', async({ mount, page }) => { test('flatten source code method +@dark-mode +@mobile', async({ mount, page }) => {
const component = await mount( const component = await mount(
<TestApp> <TestApp>
<ContractVerificationForm/> <ContractVerificationForm config={ formConfig }/>
</TestApp>, </TestApp>,
{ hooksConfig }, { hooksConfig },
); );
...@@ -30,7 +70,7 @@ test('flatten source code method +@dark-mode +@mobile', async({ mount, page }) = ...@@ -30,7 +70,7 @@ test('flatten source code method +@dark-mode +@mobile', async({ mount, page }) =
test('standard input json method', async({ mount, page }) => { test('standard input json method', async({ mount, page }) => {
const component = await mount( const component = await mount(
<TestApp> <TestApp>
<ContractVerificationForm/> <ContractVerificationForm config={ formConfig }/>
</TestApp>, </TestApp>,
{ hooksConfig }, { hooksConfig },
); );
...@@ -43,7 +83,7 @@ test('standard input json method', async({ mount, page }) => { ...@@ -43,7 +83,7 @@ test('standard input json method', async({ mount, page }) => {
test('sourcify method +@dark-mode +@mobile', async({ mount, page }) => { test('sourcify method +@dark-mode +@mobile', async({ mount, page }) => {
const component = await mount( const component = await mount(
<TestApp> <TestApp>
<ContractVerificationForm/> <ContractVerificationForm config={ formConfig }/>
</TestApp>, </TestApp>,
{ hooksConfig }, { hooksConfig },
); );
...@@ -62,7 +102,7 @@ test('sourcify method +@dark-mode +@mobile', async({ mount, page }) => { ...@@ -62,7 +102,7 @@ test('sourcify method +@dark-mode +@mobile', async({ mount, page }) => {
test('multi-part files method', async({ mount, page }) => { test('multi-part files method', async({ mount, page }) => {
const component = await mount( const component = await mount(
<TestApp> <TestApp>
<ContractVerificationForm/> <ContractVerificationForm config={ formConfig }/>
</TestApp>, </TestApp>,
{ hooksConfig }, { hooksConfig },
); );
...@@ -75,7 +115,7 @@ test('multi-part files method', async({ mount, page }) => { ...@@ -75,7 +115,7 @@ test('multi-part files method', async({ mount, page }) => {
test('vyper contract method', async({ mount, page }) => { test('vyper contract method', async({ mount, page }) => {
const component = await mount( const component = await mount(
<TestApp> <TestApp>
<ContractVerificationForm/> <ContractVerificationForm config={ formConfig }/>
</TestApp>, </TestApp>,
{ hooksConfig }, { hooksConfig },
); );
......
import { Button, chakra } from '@chakra-ui/react'; import { Button, chakra } from '@chakra-ui/react';
import { useRouter } from 'next/router';
import React from 'react'; import React from 'react';
import type { SubmitHandler } from 'react-hook-form'; import type { SubmitHandler } from 'react-hook-form';
import { useForm, FormProvider } from 'react-hook-form'; import { useForm, FormProvider } from 'react-hook-form';
import type { FormFields, VerificationMethod } from './types'; import type { FormFields } from './types';
import type { SmartContractVerificationMethod, SmartContractVerificationConfig } from 'types/api/contract';
import delay from 'lib/delay'; import delay from 'lib/delay';
import ContractVerificationFieldMethod, { VERIFICATION_METHODS } from './fields/ContractVerificationFieldMethod'; import ContractVerificationFieldMethod from './fields/ContractVerificationFieldMethod';
import ContractVerificationFlattenSourceCode from './methods/ContractVerificationFlattenSourceCode'; import ContractVerificationFlattenSourceCode from './methods/ContractVerificationFlattenSourceCode';
import ContractVerificationMultiPartFile from './methods/ContractVerificationMultiPartFile'; import ContractVerificationMultiPartFile from './methods/ContractVerificationMultiPartFile';
import ContractVerificationSourcify from './methods/ContractVerificationSourcify'; import ContractVerificationSourcify from './methods/ContractVerificationSourcify';
import ContractVerificationStandardInput from './methods/ContractVerificationStandardInput'; import ContractVerificationStandardInput from './methods/ContractVerificationStandardInput';
import ContractVerificationVyperContract from './methods/ContractVerificationVyperContract'; import ContractVerificationVyperContract from './methods/ContractVerificationVyperContract';
const METHODS = { const METHOD_COMPONENTS = {
flatten_source_code: <ContractVerificationFlattenSourceCode/>, flattened_code: <ContractVerificationFlattenSourceCode/>,
standard_input: <ContractVerificationStandardInput/>, standard_input: <ContractVerificationStandardInput/>,
sourcify: <ContractVerificationSourcify/>, sourcify: <ContractVerificationSourcify/>,
multi_part_file: <ContractVerificationMultiPartFile/>, multi_part: <ContractVerificationMultiPartFile/>,
vyper_contract: <ContractVerificationVyperContract/>, vyper_multi_part: <ContractVerificationVyperContract/>,
}; };
const ContractVerificationForm = () => { interface Props {
const router = useRouter(); method?: SmartContractVerificationMethod;
const methodFromQuery = router.query.method?.toString() as VerificationMethod; config: SmartContractVerificationConfig;
}
const ContractVerificationForm = ({ method: methodFromQuery, config }: Props) => {
const formApi = useForm<FormFields>({ const formApi = useForm<FormFields>({
mode: 'onBlur', mode: 'onBlur',
defaultValues: { defaultValues: {
method: VERIFICATION_METHODS.includes(methodFromQuery) ? methodFromQuery : undefined, method: methodFromQuery,
}, },
}); });
const { control, handleSubmit, watch, formState } = formApi; const { control, handleSubmit, watch, formState } = formApi;
...@@ -42,16 +45,19 @@ const ContractVerificationForm = () => { ...@@ -42,16 +45,19 @@ const ContractVerificationForm = () => {
const method = watch('method'); const method = watch('method');
const content = METHODS[method] || null; const content = METHOD_COMPONENTS[method] || null;
return ( return (
<FormProvider { ...formApi }> <FormProvider { ...formApi }>
<chakra.form <chakra.form
noValidate noValidate
onSubmit={ handleSubmit(onFormSubmit) } onSubmit={ handleSubmit(onFormSubmit) }
mt={ 12 }
> >
<ContractVerificationFieldMethod control={ control } isDisabled={ Boolean(method) }/> <ContractVerificationFieldMethod
control={ control }
isDisabled={ Boolean(method) }
methods={ config.verification_options }
/>
{ content } { content }
{ Boolean(method) && ( { Boolean(method) && (
<Button <Button
......
import { Code, Checkbox } from '@chakra-ui/react'; import { Code } from '@chakra-ui/react';
import { useQueryClient } from '@tanstack/react-query';
import React from 'react'; import React from 'react';
import type { ControllerRenderProps } from 'react-hook-form'; import type { ControllerRenderProps } from 'react-hook-form';
import { useFormContext, Controller } from 'react-hook-form'; import { useFormContext, Controller } from 'react-hook-form';
import type { FormFields } from '../types'; import type { FormFields } from '../types';
import type { SmartContractVerificationConfig } from 'types/api/contract';
import { getResourceKey } from 'lib/api/useApiQuery';
import useIsMobile from 'lib/hooks/useIsMobile'; import useIsMobile from 'lib/hooks/useIsMobile';
import FancySelect from 'ui/shared/FancySelect/FancySelect'; import FancySelect from 'ui/shared/FancySelect/FancySelect';
import ContractVerificationFormRow from '../ContractVerificationFormRow'; import ContractVerificationFormRow from '../ContractVerificationFormRow';
const COMPILERS = [
'v0.8.17+commit.8df45f5f',
'v0.8.16+commit.07a7930e',
'v0.8.15+commit.e14f2714',
];
const COMPILERS_NIGHTLY = [
'v0.8.18-nightly.2022.11.23+commit.eb2f874e',
'v0.8.17-nightly.2022.8.24+commit.22a0c46e',
'v0.8.16-nightly.2022.7.6+commit.b6f11b33',
];
interface Props { interface Props {
isVyper?: boolean; isVyper?: boolean;
} }
const ContractVerificationFieldCompiler = ({ isVyper }: Props) => { const ContractVerificationFieldCompiler = ({ isVyper }: Props) => {
const [ isNightly, setIsNightly ] = React.useState(false); const { formState, control } = useFormContext<FormFields>();
const { formState, control, getValues, resetField } = useFormContext<FormFields>();
const isMobile = useIsMobile(); const isMobile = useIsMobile();
const queryClient = useQueryClient();
const config = queryClient.getQueryData<SmartContractVerificationConfig>(getResourceKey('contract_verification_config'));
const options = React.useMemo(() => ( const options = React.useMemo(() => (
[ (isVyper ? config?.vyper_compiler_versions : config?.solidity_compiler_versions)?.map((option) => ({ label: option, value: option })) || []
...COMPILERS, ...(isNightly ? COMPILERS_NIGHTLY : []), ), [ config?.solidity_compiler_versions, config?.vyper_compiler_versions, isVyper ]);
].map((option) => ({ label: option, value: option }))
), [ isNightly ]);
const handleCheckboxChange = React.useCallback(() => {
if (isNightly) {
const field = getValues('compiler');
field.value.includes('nightly') && resetField('compiler', { defaultValue: null });
}
setIsNightly(prev => !prev);
}, [ getValues, isNightly, resetField ]);
const renderControl = React.useCallback(({ field }: {field: ControllerRenderProps<FormFields, 'compiler'>}) => { const renderControl = React.useCallback(({ field }: {field: ControllerRenderProps<FormFields, 'compiler'>}) => {
const error = 'compiler' in formState.errors ? formState.errors.compiler : undefined; const error = 'compiler' in formState.errors ? formState.errors.compiler : undefined;
...@@ -63,24 +45,12 @@ const ContractVerificationFieldCompiler = ({ isVyper }: Props) => { ...@@ -63,24 +45,12 @@ const ContractVerificationFieldCompiler = ({ isVyper }: Props) => {
return ( return (
<ContractVerificationFormRow> <ContractVerificationFormRow>
<> <Controller
<Controller name="compiler"
name="compiler" control={ control }
control={ control } render={ renderControl }
render={ renderControl } rules={{ required: true }}
rules={{ required: true }} />
/>
{ !isVyper && (
<Checkbox
size="lg"
mt={ 3 }
onChange={ handleCheckboxChange }
isDisabled={ formState.isSubmitting }
>
Include nightly builds
</Checkbox>
) }
</>
{ isVyper ? null : ( { isVyper ? null : (
<> <>
<span>The compiler version is specified in </span> <span>The compiler version is specified in </span>
......
import { Link } from '@chakra-ui/react'; import { Link } from '@chakra-ui/react';
import { useQueryClient } from '@tanstack/react-query';
import React from 'react'; import React from 'react';
import type { ControllerRenderProps } from 'react-hook-form'; import type { ControllerRenderProps } from 'react-hook-form';
import { useFormContext, Controller } from 'react-hook-form'; import { useFormContext, Controller } from 'react-hook-form';
import type { FormFields } from '../types'; import type { FormFields } from '../types';
import type { SmartContractVerificationConfig } from 'types/api/contract';
import { getResourceKey } from 'lib/api/useApiQuery';
import useIsMobile from 'lib/hooks/useIsMobile'; import useIsMobile from 'lib/hooks/useIsMobile';
import FancySelect from 'ui/shared/FancySelect/FancySelect'; import FancySelect from 'ui/shared/FancySelect/FancySelect';
import ContractVerificationFormRow from '../ContractVerificationFormRow'; import ContractVerificationFormRow from '../ContractVerificationFormRow';
const VERSIONS = [ interface Props {
'default', isVyper?: boolean;
'london', }
'berlin',
];
const ContractVerificationFieldEvmVersion = () => { const ContractVerificationFieldEvmVersion = ({ isVyper }: Props) => {
const { formState, control } = useFormContext<FormFields>(); const { formState, control } = useFormContext<FormFields>();
const isMobile = useIsMobile(); const isMobile = useIsMobile();
const queryClient = useQueryClient();
const config = queryClient.getQueryData<SmartContractVerificationConfig>(getResourceKey('contract_verification_config'));
const options = React.useMemo(() => ( const options = React.useMemo(() => (
VERSIONS.map((option) => ({ label: option, value: option })) (isVyper ? config?.vyper_evm_versions : config?.solidity_evm_versions)?.map((option) => ({ label: option, value: option })) || []
), [ ]); ), [ config?.solidity_evm_versions, config?.vyper_evm_versions, isVyper ]);
const renderControl = React.useCallback(({ field }: {field: ControllerRenderProps<FormFields, 'evm_version'>}) => { const renderControl = React.useCallback(({ field }: {field: ControllerRenderProps<FormFields, 'evm_version'>}) => {
const error = 'evm_version' in formState.errors ? formState.errors.evm_version : undefined; const error = 'evm_version' in formState.errors ? formState.errors.evm_version : undefined;
......
...@@ -20,30 +20,24 @@ import React from 'react'; ...@@ -20,30 +20,24 @@ import React from 'react';
import type { ControllerRenderProps, Control } from 'react-hook-form'; import type { ControllerRenderProps, Control } from 'react-hook-form';
import { Controller } from 'react-hook-form'; import { Controller } from 'react-hook-form';
import type { FormFields, VerificationMethod } from '../types'; import type { FormFields } from '../types';
import type { SmartContractVerificationMethod, SmartContractVerificationConfig } from 'types/api/contract';
import infoIcon from 'icons/info.svg'; import infoIcon from 'icons/info.svg';
export const VERIFICATION_METHODS: Array<VerificationMethod> = [
'flatten_source_code',
'standard_input',
'sourcify',
'multi_part_file',
'vyper_contract',
];
interface Props { interface Props {
control: Control<FormFields>; control: Control<FormFields>;
isDisabled?: boolean; isDisabled?: boolean;
methods: SmartContractVerificationConfig['verification_options'];
} }
const ContractVerificationFieldMethod = ({ control, isDisabled }: Props) => { const ContractVerificationFieldMethod = ({ control, isDisabled, methods }: Props) => {
const [ isPopoverOpen, setIsPopoverOpen ] = useBoolean(); const [ isPopoverOpen, setIsPopoverOpen ] = useBoolean();
const tooltipBg = useColorModeValue('gray.700', 'gray.900'); const tooltipBg = useColorModeValue('gray.700', 'gray.900');
const renderItem = React.useCallback((method: VerificationMethod) => { const renderItem = React.useCallback((method: SmartContractVerificationMethod) => {
switch (method) { switch (method) {
case 'flatten_source_code': case 'flattened_code':
return 'Via flattened source code'; return 'Via flattened source code';
case 'standard_input': case 'standard_input':
return ( return (
...@@ -91,9 +85,9 @@ const ContractVerificationFieldMethod = ({ control, isDisabled }: Props) => { ...@@ -91,9 +85,9 @@ const ContractVerificationFieldMethod = ({ control, isDisabled }: Props) => {
</Popover> </Popover>
</> </>
); );
case 'multi_part_file': case 'multi_part':
return 'Via multi-part files'; return 'Via multi-part files';
case 'vyper_contract': case 'vyper_multi_part':
return 'Vyper contract'; return 'Vyper contract';
default: default:
...@@ -105,13 +99,13 @@ const ContractVerificationFieldMethod = ({ control, isDisabled }: Props) => { ...@@ -105,13 +99,13 @@ const ContractVerificationFieldMethod = ({ control, isDisabled }: Props) => {
return ( return (
<RadioGroup defaultValue="add" colorScheme="blue" isDisabled={ isDisabled } { ...field }> <RadioGroup defaultValue="add" colorScheme="blue" isDisabled={ isDisabled } { ...field }>
<Stack spacing={ 4 }> <Stack spacing={ 4 }>
{ VERIFICATION_METHODS.map((method) => { { methods.map((method) => {
return <Radio key={ method } value={ method } size="lg">{ renderItem(method) }</Radio>; return <Radio key={ method } value={ method } size="lg">{ renderItem(method) }</Radio>;
}) } }) }
</Stack> </Stack>
</RadioGroup> </RadioGroup>
); );
}, [ isDisabled, renderItem ]); }, [ isDisabled, methods, renderItem ]);
return ( return (
<section> <section>
......
import type { Option } from 'ui/shared/FancySelect/types'; import type { Option } from 'ui/shared/FancySelect/types';
export type VerificationMethod = 'flatten_source_code' | 'standard_input' | 'sourcify' | 'multi_part_file' | 'vyper_contract'
export interface ContractLibrary { export interface ContractLibrary {
name: string; name: string;
address: string; address: string;
} }
export interface FormFieldsFlattenSourceCode { export interface FormFieldsFlattenSourceCode {
method: 'flatten_source_code'; method: 'flattened_code';
is_yul: boolean; is_yul: boolean;
name: string; name: string;
compiler: Option; compiler: Option;
...@@ -32,7 +30,7 @@ export interface FormFieldsSourcify { ...@@ -32,7 +30,7 @@ export interface FormFieldsSourcify {
} }
export interface FormFieldsMultiPartFile { export interface FormFieldsMultiPartFile {
method: 'multi_part_file'; method: 'multi_part';
compiler: Option; compiler: Option;
evm_version: Option; evm_version: Option;
is_optimization_enabled: boolean; is_optimization_enabled: boolean;
...@@ -41,7 +39,7 @@ export interface FormFieldsMultiPartFile { ...@@ -41,7 +39,7 @@ export interface FormFieldsMultiPartFile {
} }
export interface FormFieldsVyperContract { export interface FormFieldsVyperContract {
method: 'vyper_contract'; method: 'vyper_multi_part';
name: string; name: string;
compiler: Option; compiler: Option;
code: string; code: string;
......
import type { SmartContractVerificationMethod } from 'types/api/contract';
export const SUPPORTED_VERIFICATION_METHODS: Array<SmartContractVerificationMethod> = [
'flattened_code',
'standard_input',
'sourcify',
'multi_part',
'vyper_multi_part',
];
export function isValidVerificationMethod(method?: string): method is SmartContractVerificationMethod {
return method && SUPPORTED_VERIFICATION_METHODS.includes(method as SmartContractVerificationMethod) ? true : false;
}
...@@ -2,13 +2,19 @@ import { Text } from '@chakra-ui/react'; ...@@ -2,13 +2,19 @@ import { Text } from '@chakra-ui/react';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import React from 'react'; import React from 'react';
import type { SmartContractVerificationConfigRaw, SmartContractVerificationMethod } from 'types/api/contract';
import useApiQuery from 'lib/api/useApiQuery';
import { useAppContext } from 'lib/appContext'; import { useAppContext } from 'lib/appContext';
import isBrowser from 'lib/isBrowser'; import isBrowser from 'lib/isBrowser';
import link from 'lib/link/link'; import link from 'lib/link/link';
import ContractVerificationForm from 'ui/contractVerification/ContractVerificationForm'; import ContractVerificationForm from 'ui/contractVerification/ContractVerificationForm';
import { isValidVerificationMethod } from 'ui/contractVerification/utils';
import Address from 'ui/shared/address/Address'; import Address from 'ui/shared/address/Address';
import AddressIcon from 'ui/shared/address/AddressIcon'; import AddressIcon from 'ui/shared/address/AddressIcon';
import ContentLoader from 'ui/shared/ContentLoader';
import CopyToClipboard from 'ui/shared/CopyToClipboard'; import CopyToClipboard from 'ui/shared/CopyToClipboard';
import DataFetchAlert from 'ui/shared/DataFetchAlert';
import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic'; import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic';
import Page from 'ui/shared/Page/Page'; import Page from 'ui/shared/Page/Page';
import PageTitle from 'ui/shared/Page/PageTitle'; import PageTitle from 'ui/shared/Page/PageTitle';
...@@ -21,7 +27,20 @@ const ContractVerification = () => { ...@@ -21,7 +27,20 @@ const ContractVerification = () => {
const router = useRouter(); const router = useRouter();
const hash = router.query.id?.toString(); const hash = router.query.id?.toString();
const method = router.query.id?.toString(); const method = router.query.id?.toString() as SmartContractVerificationMethod | undefined;
const configQuery = useApiQuery('contract_verification_config', {
queryOptions: {
select: (data: unknown) => {
const _data = data as SmartContractVerificationConfigRaw;
return {
..._data,
verification_options: _data.verification_options.filter(isValidVerificationMethod),
};
},
enabled: Boolean(hash),
},
});
React.useEffect(() => { React.useEffect(() => {
if (method && hash) { if (method && hash) {
...@@ -31,6 +50,23 @@ const ContractVerification = () => { ...@@ -31,6 +50,23 @@ const ContractVerification = () => {
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [ ]); }, [ ]);
const content = (() => {
if (configQuery.isError) {
return <DataFetchAlert/>;
}
if (configQuery.isLoading) {
return <ContentLoader/>;
}
return (
<ContractVerificationForm
method={ method && configQuery.data.verification_options.includes(method) ? method : undefined }
config={ configQuery.data }
/>
);
})();
return ( return (
<Page> <Page>
<PageTitle <PageTitle
...@@ -39,7 +75,7 @@ const ContractVerification = () => { ...@@ -39,7 +75,7 @@ const ContractVerification = () => {
backLinkLabel="Back to contract" backLinkLabel="Back to contract"
/> />
{ hash && ( { hash && (
<Address> <Address mb={ 12 }>
<AddressIcon address={{ hash, is_contract: true, implementation_name: null }} flexShrink={ 0 }/> <AddressIcon address={{ hash, is_contract: true, implementation_name: null }} flexShrink={ 0 }/>
<Text fontFamily="heading" ml={ 2 } fontWeight={ 500 } fontSize="lg" w={{ base: '100%', lg: 'auto' }} whiteSpace="nowrap" overflow="hidden"> <Text fontFamily="heading" ml={ 2 } fontWeight={ 500 } fontSize="lg" w={{ base: '100%', lg: 'auto' }} whiteSpace="nowrap" overflow="hidden">
<HashStringShortenDynamic hash={ hash }/> <HashStringShortenDynamic hash={ hash }/>
...@@ -47,7 +83,7 @@ const ContractVerification = () => { ...@@ -47,7 +83,7 @@ const ContractVerification = () => {
<CopyToClipboard text={ hash }/> <CopyToClipboard text={ hash }/>
</Address> </Address>
) } ) }
<ContractVerificationForm/> { content }
</Page> </Page>
); );
}; };
......
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