Management API Reference

Ecosystem wallet

Signature Verification

Verifying signatures for smart contract wallets involves specific considerations since the smart contract itself cannot produce a signature. Instead, it provides a function:


_10
function isValidSignature(bytes32 _hash, bytes memory _signature) returns (bytes4 magicValue);

This function, defined in EIP-1271, is called to verify if a given signature is valid.

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 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:


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

Typed Data Signing#

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


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

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.