Skip to content
wallet.page

Sign-In with Ethereum (SIWE)

When apps need a confirmed sign-in (and not just a connect), they use Sign-In with Ethereum, or SIWE for short (EIP-4361). SIWE is a simple iteration on top of Personal Signatures with a standardized format allowing for easy parsing and verification.

The message encodes a chain identifier, uri, nonce, and issued at timestamp. It may also contain a statement provided by the app. All fields however are encoded in a human readable format and can easily be read by the user.

A complete message looks like this:

wallet.page wants you to sign in with your Ethereum account:
0xAb5801a7D9995314f5b2eA6574aB3F4D2eA09332

Sign in to wallet.page demos.

URI: https://wallet.page
Version: 1
Chain ID: 1
Nonce: a1b2c3d4e5f67890
Issued At: 2026-05-30T12:00:00.000Z

Implement it

Build the string with a helper so you do not get the newlines wrong.

import { createSiweMessage, generateSiweNonce } from "viem/siwe";
 
const message = createSiweMessage({
  domain: window.location.host,
  address,
  statement: "Sign in to My Dapp.",
  uri: window.location.origin,
  version: "1",
  chainId: 1,
  nonce: generateSiweNonce(),
});
 
await provider.request({
  method: "personal_sign",
  params: [message, address],
});

On the server, verify with verifySiweMessage (viem) or SiweMessage.verify (siwe). In the wallet UI, parse with parseSiweMessage from viem/siwe before you render.