diff --git a/src/ui/components/SignMessageButton/SignMessageButton.tsx b/src/ui/components/SignMessageButton/SignMessageButton.tsx index f1f8ae2195..58dd448eef 100644 --- a/src/ui/components/SignMessageButton/SignMessageButton.tsx +++ b/src/ui/components/SignMessageButton/SignMessageButton.tsx @@ -15,7 +15,6 @@ import { import type { TypedData } from 'src/modules/ethereum/message-signing/TypedData'; import { HStack } from 'src/ui/ui-kit/HStack'; import CheckIcon from 'jsx:src/ui/assets/checkmark-checked.svg'; -import { wait } from 'src/shared/wait'; import { WithReadonlyWarningDialog } from '../SignTransactionButton/ReadonlyWarningDialog'; type PersonalSignParams = MessageContextParams & { @@ -50,61 +49,24 @@ export const SignMessageButton = React.forwardRef(function SignMessageButton( ) { const hardwareSignRef = useRef(null); - const { mutateAsync: personalSignInner, ...personalSignMutationInner } = - useMutation({ - mutationFn: async (params: PersonalSignParams) => { - if (isDeviceAccount(wallet)) { - const { params: methodParams, ...messageContextParams } = params; - const [message] = methodParams; - invariant( - hardwareSignRef.current, - 'HardwareSignMessage must be mounted' - ); - const signature = await hardwareSignRef.current.personalSign(message); - walletPort.request('registerPersonalSign', { - message, - address: wallet.address, - ...messageContextParams, - }); - return signature; - } else { - return await walletPort.request('personalSign', params); - } - }, - }); - const { mutateAsync: personalSign, ...personalSignMutation } = useMutation({ mutationFn: async (params: PersonalSignParams) => { - const result = await personalSignInner(params); - if (!isDeviceAccount(wallet) && holdToSign) { - await wait(500); - } - return result; - }, - }); - - const { - mutateAsync: signTypedData_v4Inner, - ...signTypedData_v4MutationInner - } = useMutation({ - mutationFn: async (params: SignTypedDataParams) => { if (isDeviceAccount(wallet)) { - const { typedData, ...messageContextParams } = params; + const { params: methodParams, ...messageContextParams } = params; + const [message] = methodParams; invariant( hardwareSignRef.current, 'HardwareSignMessage must be mounted' ); - const signature = await hardwareSignRef.current.signTypedData_v4( - typedData - ); - walletPort.request('registerTypedDataSign', { - typedData, + const signature = await hardwareSignRef.current.personalSign(message); + walletPort.request('registerPersonalSign', { + message, address: wallet.address, ...messageContextParams, }); return signature; } else { - return await walletPort.request('signTypedData_v4', params); + return await walletPort.request('personalSign', params); } }, }); @@ -112,11 +74,24 @@ export const SignMessageButton = React.forwardRef(function SignMessageButton( const { mutateAsync: signTypedData_v4, ...signTypedData_v4Mutation } = useMutation({ mutationFn: async (params: SignTypedDataParams) => { - const result = await signTypedData_v4Inner(params); - if (!isDeviceAccount(wallet) && holdToSign) { - await wait(500); + if (isDeviceAccount(wallet)) { + const { typedData, ...messageContextParams } = params; + invariant( + hardwareSignRef.current, + 'HardwareSignMessage must be mounted' + ); + const signature = await hardwareSignRef.current.signTypedData_v4( + typedData + ); + walletPort.request('registerTypedDataSign', { + typedData, + address: wallet.address, + ...messageContextParams, + }); + return signature; + } else { + return await walletPort.request('signTypedData_v4', params); } - return result; }, }); @@ -124,26 +99,39 @@ export const SignMessageButton = React.forwardRef(function SignMessageButton( const isLoading = personalSignMutation.isLoading || signTypedData_v4Mutation.isLoading; - const isLoadingInner = - personalSignMutationInner.isLoading || - signTypedData_v4MutationInner.isLoading; const isSuccess = - personalSignMutationInner.isSuccess || - signTypedData_v4MutationInner.isSuccess; + personalSignMutation.isSuccess || signTypedData_v4Mutation.isSuccess; const isError = personalSignMutation.isError || signTypedData_v4Mutation.isError; + // we have small delay after using holdable button + const disabled = isLoading || isSuccess; + const title = buttonTitle || 'Sign'; + const successTitle = ( + + + Sent + + ); + return isDeviceAccount(wallet) ? ( ) : ( @@ -154,30 +142,19 @@ export const SignMessageButton = React.forwardRef(function SignMessageButton( holdToSign ? ( - - Signed - - } + successText={successTitle} submittingText="Sending..." onClick={handleClick} success={isSuccess} - submitting={isLoadingInner} - disabled={isLoading} + submitting={isLoading} + disabled={disabled} error={isError} kind={buttonKind} {...buttonProps} /> ) : ( - sendTransaction()} - holdToSignAllowed={true} - /> + {preferences ? ( + sendTransaction()} + holdToSign={Boolean(preferences.enableHoldToSignButton)} + /> + ) : null} diff --git a/src/ui/pages/History/AccelerateTransactionDialog/SpeedUp/SpeedUp.tsx b/src/ui/pages/History/AccelerateTransactionDialog/SpeedUp/SpeedUp.tsx index 5cc1abe495..713cdaafe5 100644 --- a/src/ui/pages/History/AccelerateTransactionDialog/SpeedUp/SpeedUp.tsx +++ b/src/ui/pages/History/AccelerateTransactionDialog/SpeedUp/SpeedUp.tsx @@ -20,6 +20,8 @@ import type { ExternallyOwnedAccount } from 'src/shared/types/ExternallyOwnedAcc import { Spacer } from 'src/ui/ui-kit/Spacer'; import { invariant } from 'src/shared/invariant'; import { INTERNAL_ORIGIN } from 'src/background/constants'; +import { usePreferences } from 'src/ui/features/preferences'; +import { wait } from 'src/shared/wait'; import { NetworkFee } from '../../../SendTransaction/NetworkFee'; import { useTransactionFee } from '../../../SendTransaction/TransactionConfiguration/useTransactionFee'; import { @@ -45,6 +47,7 @@ export function SpeedUp({ onSuccess: () => void; }) { const { address } = wallet; + const { preferences } = usePreferences(); const { transaction: originalTransaction } = addressAction; const [configuration, setConfiguration] = useState(DEFAULT_CONFIGURATION); const transaction = useMemo(() => { @@ -109,7 +112,12 @@ export function SpeedUp({ // a global onError handler (src/ui/shared/requests/queryClient.ts) // TODO: refactor to just emit error directly from the mutationFn onMutate: () => 'sendTransaction', - onSuccess, + onSuccess: async () => { + if (preferences?.enableHoldToSignButton) { + await wait(500); + } + onSuccess(); + }, }); return ( <> @@ -199,12 +207,14 @@ export function SpeedUp({ > Back - sendTransaction()} - holdToSignAllowed={true} - /> + {preferences ? ( + sendTransaction()} + holdToSign={Boolean(preferences.enableHoldToSignButton)} + /> + ) : null} diff --git a/src/ui/pages/SendForm/SendForm.tsx b/src/ui/pages/SendForm/SendForm.tsx index b17c3ab8d5..c30551da98 100644 --- a/src/ui/pages/SendForm/SendForm.tsx +++ b/src/ui/pages/SendForm/SendForm.tsx @@ -616,7 +616,7 @@ function SendFormComponent() { form={formId} wallet={wallet} disabled={isLoading} - holdToSignAllowed={false} + holdToSign={false} /> ) : null} diff --git a/src/ui/pages/SendTransaction/SendTransaction.tsx b/src/ui/pages/SendTransaction/SendTransaction.tsx index 9c99df1442..47778d916f 100644 --- a/src/ui/pages/SendTransaction/SendTransaction.tsx +++ b/src/ui/pages/SendTransaction/SendTransaction.tsx @@ -86,6 +86,7 @@ import { isDeviceAccount } from 'src/shared/types/validators'; import { shouldInterpretTransaction } from 'src/modules/ethereum/account-abstraction/shouldInterpretTransaction'; import { useCurrency } from 'src/modules/currency/useCurrency'; import { RenderArea } from 'react-area'; +import { wait } from 'src/shared/wait'; import { TransactionConfiguration } from './TransactionConfiguration'; import { DEFAULT_CONFIGURATION, @@ -507,6 +508,7 @@ function SendTransactionContent({ const { currency } = useCurrency(); const navigate = useNavigate(); const { singleAddress } = useAddressParams(); + const { preferences } = usePreferences(); const [configuration, setConfiguration] = useState(DEFAULT_CONFIGURATION); const { data: chainGasPrices } = useGasPrices(chain); @@ -642,7 +644,12 @@ function SendTransactionContent({ }, []); const next = params.get('next'); - function handleSentTransaction(tx: ethers.providers.TransactionResponse) { + async function handleSentTransaction( + tx: ethers.providers.TransactionResponse + ) { + if (preferences?.enableHoldToSignButton) { + await wait(500); + } const windowId = params.get('windowId'); invariant(windowId, 'windowId get-parameter is required'); windowPort.confirm(windowId, tx.hash); @@ -785,24 +792,26 @@ function SendTransactionContent({ > Cancel - sendTransaction()} - isLoading={sendTransactionMutation.isLoading} - disabled={sendTransactionMutation.isLoading} - buttonKind={ - interpretationHasCriticalWarning ? 'danger' : 'primary' - } - buttonTitle={ - interpretationHasCriticalWarning - ? 'Proceed Anyway' - : undefined - } - holdToSignAllowed={true} - /> + {preferences ? ( + sendTransaction()} + isLoading={sendTransactionMutation.isLoading} + disabled={sendTransactionMutation.isLoading} + buttonKind={ + interpretationHasCriticalWarning ? 'danger' : 'primary' + } + buttonTitle={ + interpretationHasCriticalWarning + ? 'Proceed Anyway' + : undefined + } + holdToSign={Boolean(preferences.enableHoldToSignButton)} + /> + ) : null} )} diff --git a/src/ui/pages/SignInWithEthereum/SignInWithEthereum.tsx b/src/ui/pages/SignInWithEthereum/SignInWithEthereum.tsx index 45891080d8..a905fe2de0 100644 --- a/src/ui/pages/SignInWithEthereum/SignInWithEthereum.tsx +++ b/src/ui/pages/SignInWithEthereum/SignInWithEthereum.tsx @@ -32,6 +32,7 @@ import type { SignMsgBtnHandle } from 'src/ui/components/SignMessageButton'; import { SignMessageButton } from 'src/ui/components/SignMessageButton'; import { ellipsis } from 'src/ui/shared/typography'; import { usePreferences } from 'src/ui/features/preferences'; +import { wait } from 'src/shared/wait'; import { txErrorToMessage } from '../SendTransaction/shared/transactionErrorToMessage'; import { SpeechBubble } from './SpeechBubble/SpeechBubble'; import { useFetchUTCTime } from './useFetchUTCTime'; @@ -102,7 +103,12 @@ export function SignInWithEthereum() { // a global onError handler (src/ui/shared/requests/queryClient.ts) // TODO: refactor to just emit error directly from the mutationFn onMutate: () => 'signMessage', - onSuccess: handleSignSuccess, + onSuccess: async (signature) => { + if (preferences?.enableHoldToSignButton) { + await wait(500); + } + handleSignSuccess(signature); + }, }); const handleReject = () => windowPort.reject(windowId); diff --git a/src/ui/pages/SignMessage/SignMessage.tsx b/src/ui/pages/SignMessage/SignMessage.tsx index af1fb0cb9a..68d18841b5 100644 --- a/src/ui/pages/SignMessage/SignMessage.tsx +++ b/src/ui/pages/SignMessage/SignMessage.tsx @@ -26,6 +26,7 @@ import { INTERNAL_ORIGIN } from 'src/background/constants'; import type { SignMsgBtnHandle } from 'src/ui/components/SignMessageButton'; import { SignMessageButton } from 'src/ui/components/SignMessageButton'; import { usePreferences } from 'src/ui/features/preferences'; +import { wait } from 'src/shared/wait'; import { txErrorToMessage } from '../SendTransaction/shared/transactionErrorToMessage'; function MessageRow({ message }: { message: string }) { @@ -81,7 +82,12 @@ function SignMessageContent({ // a global onError handler (src/ui/shared/requests/queryClient.ts) // TODO: refactor to just emit error directly from the mutationFn onMutate: () => 'signMessage', - onSuccess: handleSignSuccess, + onSuccess: async (signature) => { + if (preferences?.enableHoldToSignButton) { + await wait(500); + } + handleSignSuccess(signature); + }, }); const originForHref = useMemo(() => prepareForHref(origin), [origin]); diff --git a/src/ui/pages/SignTypedData/SignTypedData.tsx b/src/ui/pages/SignTypedData/SignTypedData.tsx index 7768885f8b..f7badced60 100644 --- a/src/ui/pages/SignTypedData/SignTypedData.tsx +++ b/src/ui/pages/SignTypedData/SignTypedData.tsx @@ -56,6 +56,7 @@ import type { SignMsgBtnHandle } from 'src/ui/components/SignMessageButton'; import { SignMessageButton } from 'src/ui/components/SignMessageButton'; import { useCurrency } from 'src/modules/currency/useCurrency'; import { usePreferences } from 'src/ui/features/preferences'; +import { wait } from 'src/shared/wait'; import { txErrorToMessage } from '../SendTransaction/shared/transactionErrorToMessage'; import { TypedDataAdvancedView } from './TypedDataAdvancedView'; @@ -184,7 +185,12 @@ function TypedDataDefaultView({ // a global onError handler (src/ui/shared/requests/queryClient.ts) // TODO: refactor to just emit error directly from the mutationFn onMutate: () => '_signTypedData', - onSuccess: onSignSuccess, + onSuccess: async (signature) => { + if (preferences?.enableHoldToSignButton) { + await wait(500); + } + onSignSuccess(signature); + }, } ); diff --git a/src/ui/pages/SwapForm/SwapForm.tsx b/src/ui/pages/SwapForm/SwapForm.tsx index 89425f2ebc..c5c79b3b82 100644 --- a/src/ui/pages/SwapForm/SwapForm.tsx +++ b/src/ui/pages/SwapForm/SwapForm.tsx @@ -756,7 +756,7 @@ export function SwapFormComponent() { approveMutation.isLoading || approveTxStatus === 'pending' } - holdToSignAllowed={false} + holdToSign={false} > Approve {spendPosition?.asset.symbol ?? null} @@ -792,7 +792,7 @@ export function SwapFormComponent() { quotesData.isLoading || Boolean((quote && !swapTransaction) || quotesData.error) } - holdToSignAllowed={false} + holdToSign={false} >