Skip to content

Using Smart Wallet with Sign-In with Ethereum

This guide covers creating a new Sign-In with Ethereum template project that uses Smart Wallet.

Create a project

Follow the Wagmi guide to set up a template project and connect a Smart Wallet.

Install dependencies

pnpm
pnpm install siwe

Create a new SIWE component

src/SignInWithEthereum.tsx
import React from 'react';
 
export function SignInWithEthereum() {
  return (
    <div>
      <h2>SIWE Example</h2>
    </div>
  );
}

Prompt to sign and store signature

Wagmi's signMessage function will open the Smart Wallet popup to sign the message. The signature is stored in the component's state.

src/SignInWithEthereum.tsx
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { useAccount, usePublicClient, useSignMessage } from 'wagmi';
import { SiweMessage } from 'siwe';
import type { Hex } from 'viem';
 
export function SignInWithEthereum() {
  const [signature, setSignature] = useState<Hex | undefined>(undefined);
  const { signMessage } = useSignMessage({ mutation: { onSuccess: (sig) => setSignature(sig) } });
  const account = useAccount();
 
  const siweMessage = useMemo(() => {
    return new SiweMessage({
      domain: document.location.host,
      address: account.address,
      chainId: account.chainId,
      uri: document.location.origin,
      version: '1',
      statement: 'Smart Wallet SIWE Example',
      nonce: '12345678', // replace with nonce generated by your backend
    });
  }, []);
 
  const promptToSign = () => {
    signMessage({ message: siweMessage.prepareMessage() });
  };
 
  return (
    <div>
      <h2>SIWE Example</h2>
      <button onClick={promptToSign}>Sign In with Ethereum</button>
      {signature && <p>Signature: {signature}</p>}
    </div>
  );
}

Verify the message signature

For Smart Wallet, ERC-1271 should be used to verify the SIWE message signature.

src/SignInWithEthereum.tsx
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import type { Hex } from 'viem';
import { useAccount, usePublicClient, useSignMessage } from 'wagmi';
import { SiweMessage } from 'siwe';
export function SignInWithEthereum() {
  const [signature, setSignature] = useState<Hex | undefined>(undefined);
  const [valid, setValid] = useState<boolean | undefined>(undefined); 
  const client = usePublicClient(); 
  const { signMessage } = useSignMessage({ mutation: { onSuccess: (sig) => setSignature(sig) } });
  const account = useAccount();
 
  const message = useMemo(() => {
    return new SiweMessage({
      domain: document.location.host,
      address: account.address,
      chainId: account.chainId,
      uri: document.location.origin,
      version: '1',
      statement: 'Smart Wallet SIWE Example',
      nonce: '12345678', // replace with nonce generated by your backend
    });
  }, []);
 
  const checkValid = useCallback(async () => { 
    if (!signature || !account.address || !client) return; 
    const isValid = await client.verifyMessage({  

      address: account.address, 
      message: message.prepareMessage(), 
      signature, 
    }); 
    setValid(isValid); 
  }, [signature, account]); 
 
  useEffect(() => { 
    checkValid(); 
  }, [signature, account]); 
 
  const promptToSign = () => {
    signMessage({ message: message.prepareMessage() });
  };
  return (
    <div>
      <h2>SIWE Example</h2>
      <button onClick={promptToSign}>Sign In with Ethereum</button>
      {signature && <p>Signature: {signature}</p>}
      {valid !== undefined && <p>Is valid: {valid.toString()}</p>}{/*}
    </div>
  );
}

Sign in with Ethereum

Visit your local server and click "Sign In with Ethereum"