Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
feat: Show info message when user declines tx in wallet
Signed-off-by: Emre Bogazliyanlioglu <emre@wormholelabs.xyz>
  • Loading branch information
emreboga committed Oct 15, 2025
commit b9ed712ccfff49db231f7f9ac498748bca2768b6
21 changes: 19 additions & 2 deletions src/hooks/useConfirmTransaction.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useContext, useState } from 'react';
import { useContext, useState, useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';

import config from 'config';
Expand Down Expand Up @@ -37,6 +37,7 @@ type ReturnProps = {
// errorInternal can be a result of custom validation, hence of unknown type.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
errorInternal: any | undefined;
info: string | undefined;
onConfirm: () => void;
};

Expand All @@ -49,6 +50,7 @@ const useConfirmTransaction = (props: Props): ReturnProps => {
const [errorInternal, setErrorInternal] = useState<any | undefined>(
undefined,
);
const [info, setInfo] = useState<string | undefined>(undefined);

const routeContext = useContext(RouteContext);
const { walletProvider } = useWalletProvider();
Expand Down Expand Up @@ -77,6 +79,19 @@ const useConfirmTransaction = (props: Props): ReturnProps => {

const getUSDAmount = useUSDamountGetter();

// Clear error and info when any input changes
useEffect(() => {
if (error) {
setError(undefined);
setErrorInternal(undefined);
}
if (info) {
setInfo(undefined);
}
// Only clear when these specific values change, not when error/info changes
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [sourceChain, sourceToken?.key, destChain, destToken?.key, amount, route]);

const onConfirm = async () => {
// Clear previous errors
if (error) {
Expand Down Expand Up @@ -260,7 +275,8 @@ const useConfirmTransaction = (props: Props): ReturnProps => {

if (transferError.type === ERR_USER_REJECTED) {
// User intentionally rejected in their wallet. This is not an error in the sense
// that something went wrong.
// that something went wrong, but we will show it as a warning info to the user.
setInfo(uiError);
} else {
console.error('Wormhole Connect: error completing transfer', e);

Expand All @@ -284,6 +300,7 @@ const useConfirmTransaction = (props: Props): ReturnProps => {
onConfirm,
error,
errorInternal,
info,
};
};

Expand Down
4 changes: 2 additions & 2 deletions src/utils/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export const INSUFFICIENT_LAMPORTS_REGEX =
export const SIMULATION_ACCOUNT_NOT_FOUND_REGEX =
/simulation failed:.*accountnotfound/i;
export const USER_REJECTED_REGEX = new RegExp(
'user rejected|rejected the request|rejected from user|user cancel|aborted by user|plugin closed|denied request signature',
'user rejected|rejected the request|rejected from user|user cancel|aborted by user|plugin closed|denied request signature|user denied|action_rejected|ethers-user-denied|approval denied',
'mi',
);
export const AMOUNT_IN_TOO_SMALL = new RegExp('AmountInTooSmall', 'm');
Expand Down Expand Up @@ -62,7 +62,7 @@ export function interpretTransferError(
uiErrorMessage = INSUFFICIENT_FUNDS_FOR_GAS_ERROR;
internalErrorCode = ERR_INSUFFICIENT_GAS;
} else if (USER_REJECTED_REGEX.test(e?.message)) {
uiErrorMessage = 'Transfer rejected in wallet, please try again';
uiErrorMessage = 'Wallet request declined. Transfer not started.';
internalErrorCode = ERR_USER_REJECTED;
} else if (AMOUNT_IN_TOO_SMALL.test(e?.message)) {
uiErrorMessage = 'Amount is too small for the selected route';
Expand Down
10 changes: 10 additions & 0 deletions src/views/v3/Bridge/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ function Bridge(props: BridgeProps) {
const {
error: txError,
errorInternal: txErrorInternal,
info: txInfo,
onConfirm,
} = useConfirmTransaction({ quotes });

Expand Down Expand Up @@ -418,6 +419,14 @@ function Bridge(props: BridgeProps) {
);
}, [styles.copyIcon, styles.doneIcon, errorCopied, txError, txErrorInternal]);

const transactionInfo = useMemo(() => {
if (!txInfo) {
return null;
}

return <AlertBannerV3>{txInfo}</AlertBannerV3>;
}, [txInfo]);

const hasEnteredAmount = amount && sdkAmount.whole(amount) > 0;
const hasConnectedWallets = sendingWallet.address && receivingWallet.address;

Expand Down Expand Up @@ -568,6 +577,7 @@ function Bridge(props: BridgeProps) {
) : null}
</Box>
{transactionError}
{transactionInfo}
<AmountValidationError validation={amountValidation} />
</>
)}
Expand Down
Loading