Recipe · Operations

Handling wallet rejection vs network vs revert

Three failure shapes deserve three UX shapes. Users canceling is silent. Network is a retry. Contract reverts are user-visible with a decoded reason.

The three shapes#

Every SDK write goes through viem, but the SDK's revert mapper translates viem's wallet, network, and contract errors into typed SDK classes before onError fires. You instanceof-check the SDK classes, not viem's.

components/CreateButton.tsx
ts
import {
  WalletRejectedError,
  NetworkError,
  ContractRevertError,
} from "@tokenops/sdk";

const create = useCreateVesting({ address: managerAddress });

create.mutate(args, {
  onError: (err) => {
    if (err instanceof WalletRejectedError) {
      // User clicked Cancel in the wallet, silent recovery, no toast.
      return;
    }
    if (err instanceof NetworkError) {
      // Network blip, retry the SAME mutation.
      toast.error("Network blip. Retry?");
      return;
    }
    if (err instanceof ContractRevertError) {
      // Contract reverted, show the decoded reason inline.
      toast.error(`Contract: ${err.context.revertReason ?? err.message}`);
      return;
    }
    // SDK-level (encryptor / RPC / setup), surface the message.
    toast.error(err.message);
  },
});

User rejected, be silent#

WalletRejectedErrormeans the user clicked Cancel. They KNOW the tx didn't go, a toast is noise. Reset any inline pending state and otherwise stay quiet.

Network, offer retry#

NetworkErroris RPC-side failure. Don't retry automatically without telling the user, the wallet UI already consumed their approval, so a silent retry could mint a duplicate tx if the first one secretly succeeded mid-failure.

Revert, show the reason#

ContractRevertError.context.revertReason carries the decoded revert reason (fall back to err.messagefor raw reverts the SDK couldn't decode). Pair with the product's typed error list (see /vesting/errorsetc.) to catch known classes BEFORE this fallback, then this branch is the "we haven't typed this revert yet" surface.

See also