Skip to main content

Overview

This guide shows you how to sign messages with your EVM wallet. Message signing is commonly used for authentication, proof of ownership, and off-chain data verification. The Python SDK signs messages using EIP-191 personal sign format.

Prerequisites

Basic Message Signing

import asyncio
import os
from dynamic_wallet_sdk import DynamicEvmWalletClient

async def main():
    async with DynamicEvmWalletClient(os.environ["DYNAMIC_ENV_ID"]) as client:
        await client.authenticate_api_token(os.environ["DYNAMIC_API_TOKEN"])

        signature = await client.sign_message(
            message="Hello, Dynamic!",
            address="0xYourWalletAddress",
        )
        print(f"Signature: {signature}")

asyncio.run(main())
The returned signature is a hex string (0x...), 132 characters long (65 bytes: r + s + v).

Signing with a Password-Protected Wallet

If you created your wallet with a password, pass it when signing:
signature = await client.sign_message(
    message="Hello, Dynamic!",
    address="0xYourWalletAddress",
    password="your-wallet-password",
)
Password handling:
  • If your wallet was created without a password, omit the password parameter.
  • If your wallet was created with a password, you must provide it for all signing operations.
The same password= kwarg also enables auto-recovery in fresh processes — the SDK transparently rehydrates key shares from Dynamic’s encrypted backup before signing. See Step 3 of Create an EVM Wallet for details.

Verifying a Signature

You can verify the signature off-chain using eth-account:
from eth_account import Account
from eth_account.messages import encode_defunct

message = "Hello, Dynamic!"
signature = await client.sign_message(message=message, address=address)

msg = encode_defunct(text=message)
recovered = Account.recover_message(msg, signature=signature)

assert recovered.lower() == address.lower(), "Signature mismatch!"
print("Signature verified")

Common Use Cases

Authentication Nonce

import time

nonce = str(int(time.time()))
message = f"Sign this message to authenticate: {nonce}"

signature = await client.sign_message(message=message, address=address)

Proof of Ownership

message = f"I own wallet {address}"
signature = await client.sign_message(message=message, address=address)

Next Steps