Skip to main content
Sign structured data with a user’s embedded Ethereum wallet using EIP-712. Typed data signing provides better UX and security by displaying human-readable structured information instead of raw hex strings.
This method uses Ethereum’s eth_signTypedData_v4 RPC method, implementing EIP-712. For simple message signing, see Sign Message.

Overview

EIP-712 (Typed Structured Data Hashing and Signing) enables users to sign structured, human-readable data instead of opaque hex strings. This improves both security and user experience by:
  • Displaying readable data: Users see what they’re actually signing
  • Preventing phishing: Clear structure makes malicious requests more obvious
  • Type safety: Structured format reduces errors
  • Better UX: Wallets can format data nicely in signing modals

Common Use Cases

  • Token permits: Gasless token approvals (ERC-20 Permit)
  • Meta-transactions: Sign transactions for relayers to submit
  • NFT approvals: Approve NFT transfers without gas
  • Governance voting: Structured voting data
  • Delegation: Delegate voting power or permissions

React SDK

To sign typed data, use the signTypedData method from the useSignTypedData hook:

EIP-712 Structure

Typed Data Format

The typed data object follows the EIP-712 specification:
object
required
The domain separator defining the context of the signature.Example:
object
required
The type definitions for the structured data. Must include EIP712Domain and your custom types.Example:
string
required
The primary type to sign from the types definition.Example:
object
required
The actual data to sign, matching the structure of the primaryType.Example:

Supported Types

EIP-712 supports various Solidity types:
  • Basic types: uint8 through uint256, int8 through int256, bool, address, bytes1 through bytes32, bytes, string
  • Arrays: uint256[], string[], etc.
  • Custom types: References to other defined types

Options Object

The second parameter is an optional configuration object:
object
Configuration for the signing confirmation modal UI.
Wallet
Specific wallet to use for signing. If not provided, uses the user’s default wallet.

Hook Callbacks

(result: { signature: string }) => void
Callback executed after successful signing. Receives the signature.
(error: Error) => void
Callback executed if signing fails or user cancels.

Returns

string
The hex-encoded signature produced by the wallet.
'hex'
The encoding format of the signature.

Complete Examples

ERC-20 Permit (Gasless Approval)

UI Customization

Customize the signing modal:

Hide Modal

Hiding the modal removes the user’s ability to review the structured data before signing. Only use this for trusted operations or after obtaining explicit user consent.

Best Practices

The domain separator prevents signature replay across chains and contracts:
Always include expiration to prevent old signatures from being reused:
Use nonces to prevent replay attacks:
Always verify signatures server-side:
Follow established standards (ERC-20 Permit, EIP-2612):
Provide clear error messages for common issues:

Troubleshooting

Common causes:
  • Type mismatch: Ensure types match exactly between signing and verification
  • Wrong domain: Domain must match exactly (including chainId)
  • Incorrect primaryType: Must reference a type in the types object
  • Message structure mismatch: Message must match primaryType structure
Ensure all types are properly defined:
Ensure chainId matches the network:
Configure callbacks on hook initialization:

Sign Message

Sign simple messages with personal_sign

Sign Transaction

Sign transactions without broadcasting

EIP-712 Specification

Official EIP-712 documentation

Viem Documentation

Verify typed data with viem

Next Steps