Sign-In with Ethereum

raw JSON →
4.4.0 verified Fri May 01 auth: no python

A Python implementation of Sign-In with Ethereum (EIP-4361). Supports parsing, verifying, and generating EIP-4361 messages for Ethereum authentication. Current version 4.4.0, requires Python >=3.8, <4.0. Actively maintained.

pip install siwe
error AttributeError: module 'siwe' has no attribute 'SiweMessage'
cause Old import path or incomplete install; in v4.0.0+ the class is at the top level.
fix
Use from siwe import SiweMessage (not from siwe.siwe import SiweMessage).
error TypeError: verify() got an unexpected keyword argument 'message'
cause Using v4+ API but passing arguments from earlier versions.
fix
Call verify(signature=signature) instead of verify(message=..., signature=...).
error ValueError: Invalid nonce length
cause The nonce must be at least 8 characters long according to EIP-4361. Some generated nonces may be shorter if using a custom one.
fix
Use generate_nonce() from siwe which ensures proper length, or provide a nonce of at least 8 characters.
breaking In v4.0.0, the signature verification API changed: `verify` now requires the `signature` parameter and no longer accepts `message` param. Also, `SiweMessage` no longer has a `check_valid` method.
fix Use `message.verify(signature=signature)` instead of passing separate arguments or calling deprecated methods.
deprecated Using `from siwe import SiweMessage` is correct, but importing from submodules like `siwe.siwe` is deprecated and may break in future versions.
fix Import directly from the top-level `siwe` package: `from siwe import SiweMessage`.
gotcha The `verify` method returns the recovered address (a string) on success, not a boolean. Many users expect a boolean and incorrectly check `if message.verify(signature)`. This will always be truthy if a valid address is returned.
fix Compare the recovered address to the expected signer: `recovered = message.verify(signature=signature); assert recovered == expected_address`.

Create and verify a SIWE message.

from siwe import SiweMessage, generate_nonce
from eth_account.messages import encode_defunct
from eth_account.account import Account

# Generate a nonce
nonce = generate_nonce()

# Create a SIWE message
message = SiweMessage(
    domain='example.com',
    address='0x1234...',
    uri='https://example.com',
    version='1',
    chain_id=1,
    nonce=nonce,
    issued_at='2022-01-01T00:00:00Z'
)

# Prepare message for signing
prepared = message.prepare_message()

# (Typically you'd send `prepared` to the client to sign with their wallet)
# To verify, you need the signature from the wallet
# signature = '0x...'  # signature from the client
# recovered_address = message.verify(signature=signature)
# print(recovered_address)