Commit 64c74843 authored by tom's avatar tom

contract verification: other methods

parent 532f7e7a
......@@ -90,7 +90,7 @@ const BlockEpochElectionRewardDetailsDesktop = ({ type, token }: Props) => {
{ query.isFetching && <ContentLoader maxW="200px" mt={ 3 }/> }
{ query.isError && <Text color="error" mt={ 3 }>Something went wrong. Unable to load next page.</Text> }
{ query.isError && <Text color="text.error" mt={ 3 }>Something went wrong. Unable to load next page.</Text> }
<Box h="0" w="100px" ref={ cutRef }/>
</Box>
......
......@@ -73,7 +73,7 @@ const BlockEpochElectionRewardDetailsMobile = ({ type, token }: Props) => {
{ query.isFetching && <ContentLoader maxW="200px" mt={ 3 }/> }
{ query.isError && <Text color="error" mt={ 3 }>Something went wrong. Unable to load next page.</Text> }
{ query.isError && <Text color="text.error" mt={ 3 }>Something went wrong. Unable to load next page.</Text> }
<Box h="0" w="100px" mt="-12px" ref={ cutRef }/>
</Flex>
......
......@@ -24,15 +24,15 @@ import ContractVerificationFieldAddress from './fields/ContractVerificationField
import ContractVerificationFieldLicenseType from './fields/ContractVerificationFieldLicenseType';
import ContractVerificationFieldMethod from './fields/ContractVerificationFieldMethod';
import ContractVerificationFlattenSourceCode from './methods/ContractVerificationFlattenSourceCode';
// import ContractVerificationMultiPartFile from './methods/ContractVerificationMultiPartFile';
// import ContractVerificationSolidityFoundry from './methods/ContractVerificationSolidityFoundry';
// import ContractVerificationSolidityHardhat from './methods/ContractVerificationSolidityHardhat';
// import ContractVerificationSourcify from './methods/ContractVerificationSourcify';
// import ContractVerificationStandardInput from './methods/ContractVerificationStandardInput';
// import ContractVerificationStylusGitHubRepo from './methods/ContractVerificationStylusGitHubRepo';
// import ContractVerificationVyperContract from './methods/ContractVerificationVyperContract';
// import ContractVerificationVyperMultiPartFile from './methods/ContractVerificationVyperMultiPartFile';
// import ContractVerificationVyperStandardInput from './methods/ContractVerificationVyperStandardInput';
import ContractVerificationMultiPartFile from './methods/ContractVerificationMultiPartFile';
import ContractVerificationSolidityFoundry from './methods/ContractVerificationSolidityFoundry';
import ContractVerificationSolidityHardhat from './methods/ContractVerificationSolidityHardhat';
import ContractVerificationSourcify from './methods/ContractVerificationSourcify';
import ContractVerificationStandardInput from './methods/ContractVerificationStandardInput';
import ContractVerificationStylusGitHubRepo from './methods/ContractVerificationStylusGitHubRepo';
import ContractVerificationVyperContract from './methods/ContractVerificationVyperContract';
import ContractVerificationVyperMultiPartFile from './methods/ContractVerificationVyperMultiPartFile';
import ContractVerificationVyperStandardInput from './methods/ContractVerificationVyperStandardInput';
import { prepareRequestBody, formatSocketErrors, getDefaultValues, METHOD_LABELS } from './utils';
interface Props {
......@@ -161,15 +161,15 @@ const ContractVerificationForm = ({ method: methodFromQuery, config, hash }: Pro
const methods = React.useMemo(() => {
return {
'flattened-code': <ContractVerificationFlattenSourceCode config={ config }/>,
// 'standard-input': <ContractVerificationStandardInput config={ config }/>,
// sourcify: <ContractVerificationSourcify/>,
// 'multi-part': <ContractVerificationMultiPartFile/>,
// 'vyper-code': <ContractVerificationVyperContract config={ config }/>,
// 'vyper-multi-part': <ContractVerificationVyperMultiPartFile/>,
// 'vyper-standard-input': <ContractVerificationVyperStandardInput/>,
// 'solidity-hardhat': <ContractVerificationSolidityHardhat config={ config }/>,
// 'solidity-foundry': <ContractVerificationSolidityFoundry/>,
// 'stylus-github-repository': <ContractVerificationStylusGitHubRepo/>,
'standard-input': <ContractVerificationStandardInput config={ config }/>,
sourcify: <ContractVerificationSourcify/>,
'multi-part': <ContractVerificationMultiPartFile/>,
'vyper-code': <ContractVerificationVyperContract config={ config }/>,
'vyper-multi-part': <ContractVerificationVyperMultiPartFile/>,
'vyper-standard-input': <ContractVerificationVyperStandardInput/>,
'solidity-hardhat': <ContractVerificationSolidityHardhat config={ config }/>,
'solidity-foundry': <ContractVerificationSolidityFoundry/>,
'stylus-github-repository': <ContractVerificationStylusGitHubRepo/>,
};
}, [ config ]);
const method = watch('method');
......@@ -201,7 +201,7 @@ const ContractVerificationForm = ({ method: methodFromQuery, config, hash }: Pro
<ContractVerificationFieldMethod methods={ config.verification_options }/>
</Grid>
{ content }
{ formState.errors.root?.message && <Text color="error"mt={ 4 } fontSize="sm" whiteSpace="pre-wrap">{ formState.errors.root.message }</Text> }
{ formState.errors.root?.message && <Text color="text.error" mt={ 4 } fontSize="sm" whiteSpace="pre-wrap">{ formState.errors.root.message }</Text> }
{ Boolean(method) && methodValue !== 'solidity-hardhat' && methodValue !== 'solidity-foundry' && (
<Button
size="md"
......
import { chakra, Code, Link } from '@chakra-ui/react';
import { Code } from '@chakra-ui/react';
import React from 'react';
import { useFormContext } from 'react-hook-form';
......@@ -6,6 +6,7 @@ import type { FormFields } from '../types';
import delay from 'lib/delay';
import useFetch from 'lib/hooks/useFetch';
import { Link } from 'toolkit/chakra/link';
import FormFieldText from 'ui/shared/forms/fields/FormFieldText';
import ContractVerificationFormRow from '../ContractVerificationFormRow';
......@@ -98,20 +99,19 @@ const ContractVerificationFieldCommit = ({ latestCommitHash }: Props) => {
<FormFieldText<FormFields>
name="commit_hash"
placeholder="Commit hash"
isRequired
size={{ base: 'md', lg: 'lg' }}
required
onBlur={ handleBlur }
rules={ rules }
/>
{ latestCommitHash && (
<chakra.div>
{ latestCommitHash ? (
<div>
<span >We have found the latest commit hash for the repository: </span>
<Code color="text_secondary">{ latestCommitHash.slice(0, 7) }</Code>
<span>. If you want to use it, </span>
<Link onClick={ handleUseLatestCommitClick }>click here</Link>
<span>.</span>
</chakra.div>
) }
</div>
) : null }
</ContractVerificationFormRow>
);
};
......
import { useUpdateEffect } from '@chakra-ui/react';
import { createListCollection, useUpdateEffect } from '@chakra-ui/react';
import React from 'react';
import { useFormContext } from 'react-hook-form';
import type { FormFields } from '../types';
import type { Option } from 'ui/shared/forms/inputs/select/types';
import FormFieldFancySelect from 'ui/shared/forms/fields/FormFieldFancySelect';
import FormFieldSelect from 'ui/shared/forms/fields/FormFieldSelect';
import ContractVerificationFormRow from '../ContractVerificationFormRow';
......@@ -37,18 +37,21 @@ const ContractVerificationFieldContractIndex = () => {
setOptions([]);
}, [ sources ]);
const collection = React.useMemo(() => {
return createListCollection({ items: options });
}, [ options ]);
if (options.length === 0) {
return null;
}
return (
<ContractVerificationFormRow>
<FormFieldFancySelect<FormFields, 'contract_index'>
<FormFieldSelect<FormFields, 'contract_index'>
name="contract_index"
placeholder="Contract name"
options={ options }
isRequired
isAsync={ false }
collection={ collection }
required
/>
</ContractVerificationFormRow>
);
......
......@@ -73,8 +73,7 @@ const ContractVerificationFieldGitHubRepo = ({ onCommitHashChange }: Props) => {
<FormFieldUrl<FormFields>
name="repository_url"
placeholder="GitHub repository URL"
isRequired
size={{ base: 'md', lg: 'lg' }}
required
onBlur={ handleBlur }
rules={ rules }
/>
......
import { Text, Button, Box, Flex } from '@chakra-ui/react';
import { Text, Box, Flex } from '@chakra-ui/react';
import React from 'react';
import type { ControllerRenderProps, FieldPathValue, ValidateResult } from 'react-hook-form';
import { Controller, useFormContext } from 'react-hook-form';
......@@ -6,6 +6,7 @@ import { Controller, useFormContext } from 'react-hook-form';
import type { FormFields } from '../types';
import { Mb } from 'lib/consts';
import { Button } from 'toolkit/chakra/button';
import FieldError from 'ui/shared/forms/components/FieldError';
import DragAndDropArea from 'ui/shared/forms/inputs/file/DragAndDropArea';
import FileInput from 'ui/shared/forms/inputs/file/FileInput';
......
import { Box, Link } from '@chakra-ui/react';
import { Box, createListCollection } from '@chakra-ui/react';
import { useQueryClient } from '@tanstack/react-query';
import React from 'react';
......@@ -6,8 +6,8 @@ import type { FormFields } from '../types';
import type { SmartContractVerificationConfig } from 'types/client/contract';
import { getResourceKey } from 'lib/api/useApiQuery';
import FormFieldFancySelect from 'ui/shared/forms/fields/FormFieldFancySelect';
import IconSvg from 'ui/shared/IconSvg';
import { Link } from 'toolkit/chakra/link';
import FormFieldSelect from 'ui/shared/forms/fields/FormFieldSelect';
import ContractVerificationFormRow from '../ContractVerificationFormRow';
......@@ -21,25 +21,26 @@ const ContractVerificationFieldZkCompiler = () => {
config?.zk_compiler_versions?.map((option) => ({ label: option, value: option })) || []
), [ config?.zk_compiler_versions ]);
const loadOptions = React.useCallback(async(inputValue: string) => {
return options
.filter(({ label }) => !inputValue || label.toLowerCase().includes(inputValue.toLowerCase()))
// TODO @tom2drum implement filtering the options
const collection = React.useMemo(() => {
const items = options
// .filter(({ label }) => !inputValue || label.toLowerCase().includes(inputValue.toLowerCase()))
.slice(0, OPTIONS_LIMIT);
return createListCollection({ items });
}, [ options ]);
return (
<ContractVerificationFormRow>
<FormFieldFancySelect<FormFields, 'zk_compiler'>
<FormFieldSelect<FormFields, 'zk_compiler'>
name="zk_compiler"
placeholder="ZK compiler (enter version or use the dropdown)"
placeholderIcon={ <IconSvg name="search"/> }
loadOptions={ loadOptions }
defaultOptions
isRequired
isAsync
collection={ collection }
required
/>
<Box>
<Link isExternal href="https://docs.zksync.io/zk-stack/components/compiler/specification#glossary">zksolc</Link>
<Link external href="https://docs.zksync.io/zk-stack/components/compiler/specification#glossary">zksolc</Link>
<span> compiler version.</span>
</Box>
</ContractVerificationFormRow>
......
import { Box, Flex, Link } from '@chakra-ui/react';
import { Box, Flex } from '@chakra-ui/react';
import React from 'react';
import { useFormContext } from 'react-hook-form';
import type { FormFields } from '../types';
import config from 'configs/app';
import { Link } from 'toolkit/chakra/link';
import ContractVerificationFormCodeSnippet from '../ContractVerificationFormCodeSnippet';
import ContractVerificationFormRow from '../ContractVerificationFormRow';
......@@ -29,7 +30,7 @@ const ContractVerificationSolidityFoundry = () => {
</Flex>
<Box whiteSpace="pre-wrap">
<span>Full tutorial about contract verification via Foundry on Blockscout is available </span>
<Link href="https://docs.blockscout.com/for-users/verifying-a-smart-contract/foundry-verification" target="_blank">
<Link href="https://docs.blockscout.com/for-users/verifying-a-smart-contract/foundry-verification" external>
here
</Link>
</Box>
......
import { Box, Flex, Link } from '@chakra-ui/react';
import { Box, Flex } from '@chakra-ui/react';
import React from 'react';
import { useFormContext } from 'react-hook-form';
......@@ -6,6 +6,7 @@ import type { FormFields } from '../types';
import type { SmartContractVerificationConfig } from 'types/client/contract';
import config from 'configs/app';
import { Link } from 'toolkit/chakra/link';
import ContractVerificationFormCodeSnippet from '../ContractVerificationFormCodeSnippet';
import ContractVerificationFormRow from '../ContractVerificationFormRow';
......@@ -56,7 +57,7 @@ const ContractVerificationSolidityHardhat = ({ config: formConfig }: { config: S
</Flex>
<Box whiteSpace="pre-wrap">
<span>Full tutorial about contract verification via Hardhat on Blockscout is available </span>
<Link href="https://docs.blockscout.com/for-users/verifying-a-smart-contract/hardhat-verification-plugin" target="_blank">
<Link href="https://docs.blockscout.com/for-users/verifying-a-smart-contract/hardhat-verification-plugin" external>
here
</Link>
</Box>
......
......@@ -23,7 +23,6 @@ const ContractVerificationStylusGitHubRepo = () => {
<FormFieldText<FormFields>
name="path_prefix"
placeholder="Path prefix"
size={{ base: 'md', lg: 'lg' }}
/>
<span>
The crate should be located in the root directory. If it is not the case, please specify the relative path from
......
import { Link } from '@chakra-ui/react';
import React from 'react';
import { Link } from 'toolkit/chakra/link';
import ContractVerificationMethod from '../ContractVerificationMethod';
import ContractVerificationFieldCompiler from '../fields/ContractVerificationFieldCompiler';
import ContractVerificationFieldEvmVersion from '../fields/ContractVerificationFieldEvmVersion';
......
......@@ -324,6 +324,10 @@ function reduceLibrariesArray(libraries: Array<ContractLibrary> | undefined) {
return;
}
if (libraries.every((item) => item.name === '' && item.address === '')) {
return;
}
return libraries.reduce<Record<string, string>>((result, item) => {
result[item.name] = item.address;
return result;
......
......@@ -7,7 +7,7 @@ interface Props {
}
const FieldError = ({ message, className }: Props) => {
return <Box className={ className } color="error" textStyle="sm" mt={ 2 } wordBreak="break-word">{ message }</Box>;
return <Box className={ className } color="text.error" textStyle="sm" mt={ 2 } wordBreak="break-word">{ message }</Box>;
};
export default chakra(FieldError);
import { chakra, Center, useColorModeValue } from '@chakra-ui/react';
import { chakra, Center } from '@chakra-ui/react';
import type { DragEvent } from 'react';
import React from 'react';
......@@ -50,8 +50,8 @@ const DragAndDropArea = ({ onDrop, children, className, isDisabled, fullFilePath
}
}, [ isDisabled ]);
const disabledBorderColor = useColorModeValue('blackAlpha.200', 'whiteAlpha.200');
const borderColor = isDragOver ? 'link_hovered' : 'link';
const disabledBorderColor = { _light: 'blackAlpha.200', _dark: 'whiteAlpha.200' };
const borderColor = isDragOver ? 'link.primary.hover' : 'link.primary';
return (
<Center
......@@ -61,7 +61,7 @@ const DragAndDropArea = ({ onDrop, children, className, isDisabled, fullFilePath
borderWidth="2px"
borderColor={ isDisabled ? disabledBorderColor : borderColor }
_hover={{
borderColor: isDisabled ? disabledBorderColor : 'link_hovered',
borderColor: isDisabled ? disabledBorderColor : 'link.primary.hover',
}}
borderRadius="base"
borderStyle="dashed"
......
import { InputGroup, VisuallyHiddenInput } from '@chakra-ui/react';
import { Box, VisuallyHidden } from '@chakra-ui/react';
import type { ChangeEvent } from 'react';
import React from 'react';
import type { ControllerRenderProps, FieldValues, Path } from 'react-hook-form';
import { Input } from 'toolkit/chakra/input';
interface InjectedProps {
onChange: (files: Array<File>) => void;
}
......@@ -53,17 +55,12 @@ const FileInput = <Values extends FieldValues, Names extends Path<Values>>({ chi
const content = typeof children === 'function' ? children(injectedProps) : children;
return (
<InputGroup onClick={ handleClick } onBlur={ handleInputBlur }>
<VisuallyHiddenInput
type="file"
onChange={ handleInputChange }
ref={ ref }
accept={ accept }
multiple={ multiple }
name={ field.name }
/>
<Box onClick={ handleClick } >
<VisuallyHidden>
<Input type="file" onChange={ handleInputChange } onBlur={ handleInputBlur } ref={ ref } accept={ accept } multiple={ multiple } name={ field.name }/>
</VisuallyHidden>
{ content }
</InputGroup>
</Box>
);
};
......
import { Box, Flex, Text, useColorModeValue, IconButton, chakra, Tooltip } from '@chakra-ui/react';
import { Box, Flex, Text, chakra } from '@chakra-ui/react';
import React from 'react';
import { IconButton } from 'toolkit/chakra/icon-button';
import { Tooltip } from 'toolkit/chakra/tooltip';
import type { IconName } from 'ui/shared/IconSvg';
import IconSvg from 'ui/shared/IconSvg';
......@@ -41,7 +43,6 @@ const FileSnippet = ({ file, className, index, onRemove, isDisabled, error }: Pr
const fileExtension = getFileExtension(file.name);
const fileIcon = FILE_ICONS[fileExtension] || 'files/placeholder';
const iconColor = useColorModeValue('gray.600', 'gray.400');
return (
<Flex
......@@ -54,11 +55,11 @@ const FileSnippet = ({ file, className, index, onRemove, isDisabled, error }: Pr
<IconSvg
name={ fileIcon }
boxSize="74px"
color={ error ? 'error' : iconColor }
color={ error ? 'text.error' : { _light: 'gray.600', _dark: 'gray.400' } }
mr={ 2 }
borderWidth="2px"
borderRadius="md"
borderColor={ useColorModeValue('blackAlpha.100', 'whiteAlpha.200') }
borderColor={{ _light: 'blackAlpha.100', _dark: 'whiteAlpha.200' }}
p={ 3 }
/>
<Box maxW="calc(100% - 58px - 24px)">
......@@ -68,35 +69,34 @@ const FileSnippet = ({ file, className, index, onRemove, isDisabled, error }: Pr
overflow="hidden"
textOverflow="ellipsis"
whiteSpace="nowrap"
color={ error ? 'error' : 'initial' }
color={ error ? 'text.error' : 'initial' }
>
{ file.name }
</Text>
{ Boolean(error) && (
<Tooltip
label={ error }
placement="top"
maxW={{ base: 'calc(100vw - 8px)', lg: '320px' }}
content={ error }
positioning={{ placement: 'top' }}
>
<Box cursor="pointer" display="inherit" onClick={ handleErrorHintIconClick } ml={ 1 }>
<IconSvg name="info" boxSize={ 5 } color="error"/>
<IconSvg name="info" boxSize={ 5 } color="text.error"/>
</Box>
</Tooltip>
) }
<IconButton
aria-label="remove"
icon={ <IconSvg name="cross" boxSize={ 6 }/> }
boxSize={ 6 }
variant="simple"
display="inline-block"
flexShrink={ 0 }
ml="auto"
onClick={ handleRemove }
isDisabled={ isDisabled }
disabled={ isDisabled }
alignSelf="flex-start"
/>
>
<IconSvg name="cross" boxSize={ 6 }/>
</IconButton>
</Flex>
<Text variant="secondary" mt={ 1 }>
<Text color="text.secondary" mt={ 1 }>
{ file.size.toLocaleString(undefined, { notation: 'compact', maximumFractionDigits: 2, unit: 'byte', unitDisplay: 'narrow', style: 'unit' }) }
</Text>
</Box>
......
......@@ -124,7 +124,7 @@ const TxInfo = ({ data, isLoading, socketStatus }: Props) => {
const executionFailedBadge = toAddress?.is_contract && Boolean(data.status) && data.result !== 'success' ? (
<Tooltip content="Error occurred during contract execution">
<chakra.span display="inline-flex" ml={ 2 } mr={ 1 }>
<IconSvg name="status/error" boxSize={ 4 } color="error" cursor="pointer"/>
<IconSvg name="status/error" boxSize={ 4 } color="text.error" cursor="pointer"/>
</chakra.span>
</Tooltip>
) : null;
......
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