Skip to content

Signature Verification

For a Smart Wallet, a signature is valid if it is signed by a current signer (or "owner") of the wallet.

For instance, a user might sign a message using their passkey. When the isValidSignature function (defined in EIP-1271) is called on their Smart Wallet, it validates the signature because the user's passkey is authorized as an owner.

The following section outlines how to implement both personal message signing and typed data signing using wagmi.

Message Signing

For basic message signing (personal_sign), you can use wagmi's useSignMessage hook.

Here's an example implementation:

import { useSignMessage } from 'wagmi'
 
function SignMessage() {
  const { signMessage, data: signature, isPending, error } = useSignMessage()
 
  const handlePersonalSign = () => {
    signMessage({ message: 'Hello World' })
  }
 
  return (
    <div>
      <button 
        onClick={handlePersonalSign}
        disabled={isPending}
      >
        {isPending ? 'Signing...' : 'Sign Message'}
      </button>
      
      {signature && (
        <div>
          <p>Signature: {signature}</p>
        </div>
      )}
      
      {error && <div>Error: {error.message}</div>}
    </div>
  )
}

Typed Data Signing

For more complex signatures, you can use typed data signing (EIP-712) with wagmi's useSignTypedData hook:

import { useSignTypedData } from 'wagmi'
 
function SignTypedData() {
  const { signTypedData, data: signature, isPending, error } = useSignTypedData()
 
  const types = {
    Mail: [
      {name: 'from', type: 'Person'},
      {name: 'to', type: 'Person'},
      {name: 'content', type: 'string'},
    ],
    Person: [
      {name: 'name', type: 'string'},
      {name: 'wallet', type: 'address'},
    ],
  }
 
  const handleTypedMessage = () => {
    signTypedData({
      domain: {
        chainId: 1, // Replace with your chain ID
        name: 'Example DApp',
        verifyingContract: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC',
        version: '1',
      },
      types,
      message: {
        from: { name: 'Alice', wallet: '0x2111111111111111111111111111111111111111' },
        to: { name: 'Bob', wallet: '0x3111111111111111111111111111111111111111' },
        content: 'Hello!',
      },
      primaryType: 'Mail',
    })
  }
 
  return (
    <div>
      <button 
        onClick={handleTypedMessage}
        disabled={isPending}
      >
        {isPending ? 'Signing...' : 'Sign Typed Data'}
      </button>
      
      {signature && (
        <div>
          <p>Signature: {signature}</p>
        </div>
      )}
      
      {error && <div>Error: {error.message}</div>}
    </div>
  )
}

Both signing methods work seamlessly with Smart Contract Wallets that implement EIP-1271, allowing for a consistent signing experience across EOA and Smart Contract Wallets.