From 1cb6dfd8571e6921bc137f07f77ab93bce8e8072 Mon Sep 17 00:00:00 2001 From: katspaugh Date: Wed, 18 Sep 2024 16:03:19 +0200 Subject: [PATCH] Refactor: a review screen for recovery attempts --- next-env.d.ts | 2 +- .../RecoveryAttempt/RecoveryAttemptReview.tsx | 93 +++++++++++++++++++ .../tx-flow/flows/RecoveryAttempt/index.tsx | 13 +++ src/components/tx-flow/flows/index.ts | 1 + .../ExecuteRecoveryButton/index.tsx | 33 +------ 5 files changed, 112 insertions(+), 30 deletions(-) create mode 100644 src/components/tx-flow/flows/RecoveryAttempt/RecoveryAttemptReview.tsx create mode 100644 src/components/tx-flow/flows/RecoveryAttempt/index.tsx diff --git a/next-env.d.ts b/next-env.d.ts index 4f11a03dc6..a4a7b3f5cf 100644 --- a/next-env.d.ts +++ b/next-env.d.ts @@ -2,4 +2,4 @@ /// // NOTE: This file should not be edited -// see https://nextjs.org/docs/basic-features/typescript for more information. +// see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information. diff --git a/src/components/tx-flow/flows/RecoveryAttempt/RecoveryAttemptReview.tsx b/src/components/tx-flow/flows/RecoveryAttempt/RecoveryAttemptReview.tsx new file mode 100644 index 0000000000..d34f5ea241 --- /dev/null +++ b/src/components/tx-flow/flows/RecoveryAttempt/RecoveryAttemptReview.tsx @@ -0,0 +1,93 @@ +import { type SyntheticEvent, useState, useContext, useCallback } from 'react' +import { CircularProgress, CardActions, Button, Typography, Stack, Divider } from '@mui/material' +import EthHashInfo from '@/components/common/EthHashInfo' +import CheckWallet from '@/components/common/CheckWallet' +import { Errors, trackError } from '@/services/exceptions' +import { dispatchRecoveryExecution } from '@/features/recovery/services/recovery-sender' +import useWallet from '@/hooks/wallets/useWallet' +import useSafeInfo from '@/hooks/useSafeInfo' +import type { TransactionAddedEvent } from '@gnosis.pm/zodiac/dist/cjs/types/Delay' +import ErrorMessage from '@/components/tx/ErrorMessage' +import TxCard from '@/components/tx-flow/common/TxCard' +import FieldsGrid from '@/components/tx/FieldsGrid' +import { TxModalContext } from '../..' + +export type RecoveryAttemptReviewProps = { + params: { + args: TransactionAddedEvent.Log['args'] + address: string + } +} + +const RecoveryAttemptReview = ({ params }: RecoveryAttemptReviewProps) => { + const [isPending, setIsPending] = useState(false) + const [error, setError] = useState() + const wallet = useWallet() + const { safe } = useSafeInfo() + const { setTxFlow } = useContext(TxModalContext) + + const onFormSubmit = useCallback( + async (e: SyntheticEvent) => { + e.preventDefault() + + if (!wallet) return + + setError(undefined) + setIsPending(true) + + try { + await dispatchRecoveryExecution({ + provider: wallet.provider, + chainId: safe.chainId, + args: params.args, + delayModifierAddress: params.address, + signerAddress: wallet.address, + }) + setTxFlow(undefined) + } catch (err) { + trackError(Errors._812, err) + setError(err as Error) + } + + setIsPending(false) + }, + [wallet, safe, params, setTxFlow], + ) + + return ( + +
+ + {params?.address && ( + + + + )} + Confirm or reject within the review time window. + {error && Error submitting the transaction.} + + + + + + {/* Submit button, also available to non-owner role members */} + + {(isOk) => ( + + )} + + + +
+ ) +} + +export default RecoveryAttemptReview diff --git a/src/components/tx-flow/flows/RecoveryAttempt/index.tsx b/src/components/tx-flow/flows/RecoveryAttempt/index.tsx new file mode 100644 index 0000000000..b2da67580a --- /dev/null +++ b/src/components/tx-flow/flows/RecoveryAttempt/index.tsx @@ -0,0 +1,13 @@ +import TxLayout from '@/components/tx-flow/common/TxLayout' +import SaveAddressIcon from '@/public/images/common/save-address.svg' +import RecoveryAttemptReview, { type RecoveryAttemptReviewProps } from './RecoveryAttemptReview' + +const RecoveryAttemptFlow = ({ params }: { params: RecoveryAttemptReviewProps['params'] }) => { + return ( + + + + ) +} + +export default RecoveryAttemptFlow diff --git a/src/components/tx-flow/flows/index.ts b/src/components/tx-flow/flows/index.ts index fd28c11e8b..48335b9bb8 100644 --- a/src/components/tx-flow/flows/index.ts +++ b/src/components/tx-flow/flows/index.ts @@ -25,3 +25,4 @@ export const SuccessScreenFlow = dynamic(() => import('./SuccessScreen')) export const TokenTransferFlow = dynamic(() => import('./TokenTransfer')) export const UpdateSafeFlow = dynamic(() => import('./UpdateSafe')) export const UpsertRecoveryFlow = dynamic(() => import('./UpsertRecovery')) +export const RecoveryAttemptFlow = dynamic(() => import('./RecoveryAttempt')) diff --git a/src/features/recovery/components/ExecuteRecoveryButton/index.tsx b/src/features/recovery/components/ExecuteRecoveryButton/index.tsx index a5d6e63bcd..8bee4a0ef3 100644 --- a/src/features/recovery/components/ExecuteRecoveryButton/index.tsx +++ b/src/features/recovery/components/ExecuteRecoveryButton/index.tsx @@ -1,19 +1,14 @@ -import useWallet from '@/hooks/wallets/useWallet' import { Button, Tooltip } from '@mui/material' import { useContext } from 'react' import type { SyntheticEvent, ReactElement } from 'react' import CheckWallet from '@/components/common/CheckWallet' -import { dispatchRecoveryExecution } from '@/features/recovery/services/recovery-sender' -import useOnboard from '@/hooks/wallets/useOnboard' -import useSafeInfo from '@/hooks/useSafeInfo' import { useRecoveryTxState } from '@/features/recovery/hooks/useRecoveryTxState' -import { Errors, trackError } from '@/services/exceptions' -import { asError } from '@/services/exceptions/utils' -import { RecoveryListItemContext } from '../RecoveryListItem/RecoveryListItemContext' import type { RecoveryQueueItem } from '@/features/recovery/services/recovery-state' import useIsWrongChain from '@/hooks/useIsWrongChain' import { useCurrentChain } from '@/hooks/useChains' +import { TxModalContext } from '@/components/tx-flow' +import { RecoveryAttemptFlow } from '@/components/tx-flow/flows' export function ExecuteRecoveryButton({ recovery, @@ -22,37 +17,17 @@ export function ExecuteRecoveryButton({ recovery: RecoveryQueueItem compact?: boolean }): ReactElement { - const { setSubmitError } = useContext(RecoveryListItemContext) const { isExecutable, isNext, isPending } = useRecoveryTxState(recovery) - const onboard = useOnboard() - const wallet = useWallet() - const { safe } = useSafeInfo() const isDisabled = !isExecutable || isPending const isWrongChain = useIsWrongChain() const chain = useCurrentChain() + const { setTxFlow } = useContext(TxModalContext) const onClick = async (e: SyntheticEvent) => { e.stopPropagation() e.preventDefault() - if (!onboard || !wallet) { - return - } - - try { - await dispatchRecoveryExecution({ - provider: wallet.provider, - chainId: safe.chainId, - args: recovery.args, - delayModifierAddress: recovery.address, - signerAddress: wallet.address, - }) - } catch (_err) { - const err = asError(_err) - - trackError(Errors._812, e) - setSubmitError(err) - } + setTxFlow() } return (