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"