Skip to main content

Documentation Index

Fetch the complete documentation index at: https://www.dynamic.xyz/docs/llms.txt

Use this file to discover all available pages before exploring further.

Overview

DynamicEvmWalletClient::sign_message signs a UTF-8 message using EIP-191 (personal_sign) and returns a 0x-prefixed r || s || v signature (65 bytes / 130 hex chars). Message signing is commonly used for authentication, nonce verification, and data integrity checks.

Prerequisites

Basic Message Signing

The Rust SDK is stateless — every sign call requires WalletProperties and external_server_key_shares. Load both from where you persisted them at wallet creation time.
use dynamic_waas_sdk::{ServerKeyShare, WalletProperties};
use dynamic_waas_sdk_evm::DynamicEvmWalletClient;

let evm = DynamicEvmWalletClient::new(&client);

// Load the metadata + shares you persisted at creation time.
let wallet_properties: WalletProperties = serde_json::from_str(
    &redis.get(format!("wallet:{}", account_address)).await?,
)?;
let external_server_key_shares: Vec<ServerKeyShare> = serde_json::from_slice(
    &vault.read(format!("wallet:{}/shares", account_address)).await?,
)?;

let signature = evm
    .sign_message(
        &wallet_properties,
        &external_server_key_shares,
        "Hello, World!",
    )
    .await?;

println!("Signature: {signature}");
signature is a 0x-prefixed hex string — pass it directly to any EIP-191 verifier (alloy, ethers, viem, etc).

Verifying the signer locally

Because the signature is standard EIP-191, you can recover the signer with any EVM library. With alloy:
use alloy_primitives::{Address, Signature};

let prefixed = format!(
    "\x19Ethereum Signed Message:\n{}{}",
    "Hello, World!".len(),
    "Hello, World!",
);
let digest = alloy_primitives::keccak256(prefixed.as_bytes());
let sig: Signature = signature.parse()?;
let recovered: Address = sig.recover_address_from_prehash(&digest)?;

assert_eq!(
    recovered.to_checksum(None),
    wallet_properties.account_address,
);

Common Use Cases

Authentication

let nonce = chrono::Utc::now().timestamp_millis().to_string();
let message = format!("Sign this message to authenticate: {nonce}");
let signature = evm
    .sign_message(&wallet_properties, &external_server_key_shares, &message)
    .await?;

Data Integrity

let payload = serde_json::json!({ "user_id": 123, "action": "transfer", "amount": "100" });
let message = serde_json::to_string(&payload)?;
let signature = evm
    .sign_message(&wallet_properties, &external_server_key_shares, &message)
    .await?;

Next Steps