diff --git a/src/components/new-safe/CreateSafe/index.tsx b/src/components/new-safe/CreateSafe/index.tsx index 0443c4d7b8..1571ddaaee 100644 --- a/src/components/new-safe/CreateSafe/index.tsx +++ b/src/components/new-safe/CreateSafe/index.tsx @@ -13,6 +13,7 @@ import { Card, CardContent, Typography } from '@mui/material' import { useRouter } from 'next/router' import { AppRoutes } from '@/config/routes' import { CREATE_SAFE_CATEGORY } from '@/services/analytics' +import CreateSafeStep3 from '@/components/new-safe/steps/Step3' export type NewSafeFormData = { name: string @@ -33,6 +34,11 @@ export const CreateSafeSteps: TxStepperProps['steps'] = [ 'Here you can add owners to your Safe and determine how many owners need to confirm before making a successful transaction', render: (data, onSubmit, onBack) => , }, + { + title: 'Review', + subtitle: `You're about to create a new Safe and will have to confirm a transaction with your currently connected wallet.`, + render: (data, onSubmit, onBack) => , + }, ] const CreateSafe = () => { diff --git a/src/components/new-safe/StepCard/index.tsx b/src/components/new-safe/StepCard/index.tsx index 2037eb412f..8f87ec04b9 100644 --- a/src/components/new-safe/StepCard/index.tsx +++ b/src/components/new-safe/StepCard/index.tsx @@ -8,34 +8,32 @@ const StepCard = ({ subheader, content, actions, + step = 1, }: { title: string subheader: string content: ReactElement actions: ReactElement -}): ReactElement => { // TODO: `step` and `LinearProgress` will be set via stepper hook - const step = 1 - - return ( - - - - {step} - - } - className={css.header} - /> - {content} - {actions} - - ) -} + step?: number +}): ReactElement => ( + + + + {step} + + } + className={css.header} + /> + {content} + {actions} + +) export default StepCard diff --git a/src/components/new-safe/steps/Step2/index.tsx b/src/components/new-safe/steps/Step2/index.tsx index 5e22ae4d80..503788f8e6 100644 --- a/src/components/new-safe/steps/Step2/index.tsx +++ b/src/components/new-safe/steps/Step2/index.tsx @@ -40,7 +40,6 @@ const CreateSafeStep2 = ({ const { register, handleSubmit, control, watch } = formMethods const allFormData = watch() - const currentThreshold = watch(CreateSafeStep2Fields.threshold) const { fields: ownerFields, append: appendOwner, remove: removeOwner } = useFieldArray({ control, name: 'owners' }) diff --git a/src/components/new-safe/steps/Step3/index.tsx b/src/components/new-safe/steps/Step3/index.tsx new file mode 100644 index 0000000000..d5ca2f8909 --- /dev/null +++ b/src/components/new-safe/steps/Step3/index.tsx @@ -0,0 +1,162 @@ +import { useMemo, type ReactElement } from 'react' +import { FormProvider, useForm } from 'react-hook-form' +import { Button, Grid, Typography, Divider, Box } from '@mui/material' +import ChainIndicator from '@/components/common/ChainIndicator' +import EthHashInfo from '@/components/common/EthHashInfo' +import type { NamedAddress } from '@/components/create-safe/types' +import { useCurrentChain } from '@/hooks/useChains' +import useGasPrice from '@/hooks/useGasPrice' +import { useEstimateSafeCreationGas } from '@/components/create-safe/useEstimateSafeCreationGas' +import { formatVisualAmount } from '@/utils/formatters' +import type { StepRenderProps } from '@/components/new-safe/CardStepper/useCardStepper' +import type { NewSafeFormData } from '@/components/new-safe/CreateSafe' +import css from './styles.module.css' + +enum CreateSafeStep3Fields { + name = 'name', + owners = 'owners', + threshold = 'threshold', +} + +type CreateSafeStep3Form = { + name: string + owners: NamedAddress[] + threshold: number + networkFee: string +} + +const STEP_3_FORM_ID = 'create-safe-step-3-form' + +const ReviewRow = ({ name, value }: { name: string; value: ReactElement }) => { + return ( + <> + + {name} + + + {value} + + + ) +} + +const CreateSafeStep3 = ({ + onSubmit, + onBack, + data, +}: Pick, 'onSubmit' | 'data' | 'onBack'>): ReactElement => { + const chain = useCurrentChain() + const { maxFeePerGas, maxPriorityFeePerGas } = useGasPrice() + const saltNonce = useMemo(() => Date.now(), []) + + const safeParams = useMemo(() => { + return { + owners: data.owners.map((owner) => owner.address), + threshold: data.threshold, + saltNonce, + } + }, [data.owners, data.threshold, saltNonce]) + + const { gasLimit } = useEstimateSafeCreationGas(safeParams) + + const totalFee = + gasLimit && maxFeePerGas && maxPriorityFeePerGas + ? formatVisualAmount(maxFeePerGas.add(maxPriorityFeePerGas).mul(gasLimit), chain?.nativeCurrency.decimals) + : '> 0.001' + + const formMethods = useForm({ + mode: 'all', + defaultValues: { + [CreateSafeStep3Fields.name]: data.name, + [CreateSafeStep3Fields.owners]: data.owners, + [CreateSafeStep3Fields.threshold]: data.threshold, + }, + }) + + const { handleSubmit, getValues } = formMethods + + const allFormData = getValues() + + const handleBack = () => { + onBack(allFormData) + } + + return ( +
+ + + + + } /> + {data.name}} /> + + {data.owners.map((owner, index) => ( + + ))} + + } + /> + + {data.threshold} out of {data.owners.length} owner(s) + + } + /> + + + + + + + + + + + ≈ {totalFee} {chain?.nativeCurrency.symbol} + + + + } + /> + + + + You will have to confirm a transaction with your currently connected wallet. + + + + + + + + + + + + + + +
+ ) +} + +export default CreateSafeStep3 diff --git a/src/components/new-safe/steps/Step3/styles.module.css b/src/components/new-safe/steps/Step3/styles.module.css new file mode 100644 index 0000000000..31a8389b86 --- /dev/null +++ b/src/components/new-safe/steps/Step3/styles.module.css @@ -0,0 +1,5 @@ +.ownersArray { + display: flex; + flex-direction: column; + gap: var(--space-2); +}