Commit cf97a102 authored by tom's avatar tom

ui changes

parent 3ebdf002
import { Modal, ModalBody, ModalCloseButton, ModalContent, ModalHeader, ModalOverlay } from '@chakra-ui/react';
import { Icon, Modal, ModalBody, ModalCloseButton, ModalContent, ModalHeader, ModalOverlay, Alert, Link } from '@chakra-ui/react';
import React from 'react';
import type { SubmitHandler } from 'react-hook-form';
import { useForm, FormProvider } from 'react-hook-form';
......@@ -6,6 +6,8 @@ import { useForm, FormProvider } from 'react-hook-form';
import type { AddressVerificationFormFields } from './types';
import appConfig from 'configs/app/config';
import eastArrowIcon from 'icons/arrows/east.svg';
import type { ResourceError } from 'lib/api/resources';
import useApiFetch from 'lib/api/useApiFetch';
import Web3ModalProvider from 'ui/shared/Web3ModalProvider';
......@@ -20,6 +22,7 @@ interface Props {
const AddressVerificationModal = ({ isOpen, onClose }: Props) => {
const [ stepIndex, setStepIndex ] = React.useState(0);
const [ error, setError ] = React.useState('');
const apiFetch = useApiFetch();
const formApi = useForm<AddressVerificationFormFields>({
......@@ -31,12 +34,20 @@ const AddressVerificationModal = ({ isOpen, onClose }: Props) => {
setStepIndex((prev) => prev + 1);
}, []);
const handleGoToPrevStep = React.useCallback(() => {
setStepIndex((prev) => prev - 1);
}, []);
const handleClose = React.useCallback(() => {
onClose();
setStepIndex(0);
formApi.reset();
}, [ formApi, onClose ]);
const handleSignClick = React.useCallback(() => {
setError('');
}, []);
const onFormSubmit: SubmitHandler<AddressVerificationFormFields> = React.useCallback(async(data) => {
// eslint-disable-next-line no-console
console.log('__>__', data);
......@@ -45,17 +56,23 @@ const AddressVerificationModal = ({ isOpen, onClose }: Props) => {
message: data.message,
signature: data.signature,
};
try {
await apiFetch('address_verification', {
fetchParams: { method: 'POST', body },
pathParams: { chainId: appConfig.network.id },
});
} catch (error: unknown) {
const _error = error as ResourceError<{message: string}>;
setError(_error.payload?.message || 'Oops! Something went wrong');
}
}, [ apiFetch ]);
const onSubmit = handleSubmit(onFormSubmit);
const steps = [
{ title: 'Verify new address ownership', content: <AddressVerificationStepAddress onContinue={ handleGoToNextStep }/> },
{ title: 'Copy message to sign', content: <AddressVerificationStepSignature onContinue={ handleGoToNextStep } onSubmit={ onSubmit }/> },
{ title: 'Sign message', content: <AddressVerificationStepSignature onSubmit={ onSubmit } onSign={ handleSignClick }/> },
{ title: 'Congrats! Address is verified.', content: <AddressVerificationStepSuccess onShowListClick={ handleClose } onAddTokenClick={ handleClose }/> },
];
const step = steps[stepIndex];
......@@ -64,12 +81,20 @@ const AddressVerificationModal = ({ isOpen, onClose }: Props) => {
<Modal isOpen={ isOpen } onClose={ handleClose } size={{ base: 'full', lg: 'md' }}>
<ModalOverlay/>
<ModalContent>
<ModalHeader fontWeight="500" textStyle="h3" mb={ 6 }>{ step.title }</ModalHeader>
<ModalHeader fontWeight="500" textStyle="h3" mb={ 6 }>
{ stepIndex !== 0 && (
<Link mr={ 3 } onClick={ handleGoToPrevStep }>
<Icon as={ eastArrowIcon } boxSize={ 6 } transform="rotate(180deg)" verticalAlign="middle"/>
</Link>
) }
<span>{ step.title }</span>
</ModalHeader>
<ModalCloseButton/>
<ModalBody mb={ 0 }>
<Web3ModalProvider>
<FormProvider { ...formApi }>
<form noValidate onSubmit={ onSubmit }>
{ error && <Alert status="warning" mb={ 6 }>{ error }</Alert> }
{ step.content }
</form>
</FormProvider>
......
......@@ -5,7 +5,6 @@ import { Controller, useFormContext } from 'react-hook-form';
import type { AddressVerificationFormFields } from '../types';
import appConfig from 'configs/app/config';
import dayjs from 'lib/date/dayjs';
import InputPlaceholder from 'ui/shared/InputPlaceholder';
......@@ -36,7 +35,7 @@ const AddressVerificationFieldMessage = ({ isDisabled }: Props) => {
const address = getValues('address');
// eslint-disable-next-line max-len
const defaultValue = `[${ appConfig.host } ${ dayjs().format('YYYY-MM-DD HH:mm:ss') }] I hereby verify that I am the owner/creator of the address ${ address }.`;
const defaultValue = `[Blockscout.com] [${ dayjs().format('YYYY-MM-DD HH:mm:ss') }] I, hereby verify that I am the owner/creator of the address [${ address }]`;
return (
<Controller
......
import { Box, Button, Flex, Link } from '@chakra-ui/react';
import { Alert, Box, Button, Flex, Radio, RadioGroup } from '@chakra-ui/react';
import React from 'react';
import { useFormContext } from 'react-hook-form';
import { useSignMessage } from 'wagmi';
import type { AddressVerificationFormFields } from '../types';
import useToast from 'lib/hooks/useToast';
import AddressVerificationFieldAddress from '../fields/AddressVerificationFieldAddress';
import AddressVerificationFieldMessage from '../fields/AddressVerificationFieldMessage';
import AddressVerificationFieldSignature from '../fields/AddressVerificationFieldSignature';
interface Props {
onContinue: () => void;
onSubmit: () => void;
onSign: () => void;
}
const AddressVerificationStepSignature = ({ onContinue, onSubmit }: Props) => {
const [ isManualSigning, setIsManualSigning ] = React.useState(false);
const AddressVerificationStepSignature = ({ onSubmit, onSign }: Props) => {
const [ signMethod, setSignMethod ] = React.useState<'wallet' | 'manually'>('wallet');
const [ error, setError ] = React.useState('');
const toast = useToast();
const { formState, trigger, getValues, setValue } = useFormContext<AddressVerificationFormFields>();
const { signMessage } = useSignMessage({
const { getValues, setValue, formState } = useFormContext<AddressVerificationFormFields>();
const { signMessage, isLoading: isSigning } = useSignMessage({
onSuccess: (data) => {
setValue('signature', data);
onSubmit();
},
onError: (error) => {
toast({
position: 'top-right',
title: 'Error',
description: (error as Error)?.message || 'Something went wrong',
status: 'error',
variant: 'subtle',
isClosable: true,
});
setError((error as Error)?.message || 'Something went wrong');
},
});
const handleVerifyButtonClick = React.useCallback(() => {
if (!formState.isValid) {
trigger('signature');
trigger('message');
return;
}
onContinue();
}, [ formState, onContinue, trigger ]);
const handleSignMethodChange = React.useCallback((value: typeof signMethod) => {
setSignMethod(value);
setError('');
}, []);
const handleWeb3SignClick = React.useCallback(() => {
onSign();
const message = getValues('message');
signMessage({ message });
}, [ getValues, signMessage ]);
}, [ getValues, onSign, signMessage ]);
const handleManualSignClick = React.useCallback(() => {
setIsManualSigning(true);
}, []);
const buttons = isManualSigning ? (
<>
<Button size="lg" onClick={ handleVerifyButtonClick }>
Verify ownership
</Button>
<Box>
<span>Contact </span>
<Link>support@blockscout.com</Link>
</Box>
</>
) : (
<>
<Button size="lg" onClick={ handleManualSignClick }>
Sign manually
</Button>
<Button size="lg" onClick={ handleWeb3SignClick }>
Sign via web3 wallet
</Button>
</>
);
onSign();
onSubmit();
}, [ onSign, onSubmit ]);
return (
<Box>
{ error && <Alert status="warning" mb={ 6 }>{ error }</Alert> }
<Box mb={ 8 }>
Copy the message below and sign it using the Blockscout sign message provider of your choice.
Please select the address to sign and copy the message below and sign it using the Blockscout sign message provider of your choice...
</Box>
<Flex rowGap={ 5 } flexDir="column">
<AddressVerificationFieldAddress isDisabled/>
<AddressVerificationFieldMessage isDisabled={ !isManualSigning }/>
{ isManualSigning && <AddressVerificationFieldSignature/> }
<AddressVerificationFieldMessage isDisabled/>
<RadioGroup onChange={ handleSignMethodChange } value={ signMethod } display="flex" flexDir="column" rowGap={ 4 }>
<Radio value="wallet">Sign via Web3 wallet</Radio>
<Radio value="manually">Sign manually</Radio>
</RadioGroup>
{ signMethod === 'manually' && <AddressVerificationFieldSignature/> }
</Flex>
<Box mt={ 8 }>
<span>{ `Check our article on "` }</span>
<Link>How to sign message?</Link>
<span>{ `" if you have not done before.` }</span>
</Box>
<Flex alignItems="center" mt={ 8 } columnGap={ 5 }>
{ buttons }
<Button
size="lg"
onClick={ signMethod === 'manually' ? handleManualSignClick : handleWeb3SignClick }
isLoading={ formState.isSubmitting || isSigning }
loadingText={ isSigning ? 'Signing' : 'Verifying' }
>
{ signMethod === 'manually' ? 'Verify' : 'Sign and verify' }
</Button>
</Flex>
</Box>
);
......
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