> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dynamic.xyz/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Create EVM Wallet

> Learn how to create and manage EVM server wallets with Dynamic's Rust SDK

## Overview

This guide walks you through creating EVM wallets using Dynamic's Rust SDK. You'll learn how to set up different threshold signature schemes and understand the security implications of each choice.

## Prerequisites

Before you begin, make sure you have:

* [Set up your Dynamic project](/rust/quickstart)
* [Created an authenticated client](/rust/quickstart)
* [Enabled EVM chains in your dashboard](https://app.dynamic.xyz/dashboard/chains)

## Step 1: Choose Your Security Model

Dynamic supports two threshold signature schemes, each offering different security and availability trade-offs:

### `TwoOfTwo` (Recommended for most use cases)

* **Security**: Highest — requires both your server and Dynamic's infrastructure
* **Availability**: Lower — both parties must be online
* **Use case**: High-value transactions, maximum security

### `TwoOfThree`

* **Security**: High — requires 2 out of 3 shares
* **Availability**: Medium — can tolerate one party being offline
* **Use case**: Balanced security and availability

## Step 2: Choose Your Backup Mode

Every call to `create_wallet_account` returns a `Vec<ServerKeyShare>` — the customer-side half of the MPC key. You **always vault this share in your own infrastructure** for day-to-day signing; the chain clients in 0.0.3 require it as an explicit argument on every sign / export call.

The `back_up_to_dynamic` flag controls whether Dynamic *also* keeps an encrypted copy for disaster recovery:

### `back_up_to_dynamic: true` (recommended)

The SDK encrypts your share with `password` (AES-256-GCM) and uploads the encrypted blob to Dynamic's key share service. You still receive the share locally in the return value and still vault it yourself. If you ever lose your vaulted copy, you can recover it from Dynamic's backup using [`run_recover_key_shares`](https://docs.rs/dynamic-waas-sdk) with the same `password`.

<Info>
  **`password` is required when `back_up_to_dynamic: true`.** The SDK rejects the call with `Error::InvalidArgument` if you pass `None`. The password never leaves your server — it's used locally to derive an AES-256-GCM key that wraps the share before upload, and the same password is needed later to unwrap the recovered blob.
</Info>

### `back_up_to_dynamic: false`

Dynamic does **not** store any copy of the share. You are the only holder. `password` is optional in this mode. **Losing the share means permanently losing access to the wallet.**

| Mode                        | Local vault | Dynamic backup        | `password` at create | Disaster recovery                   |
| --------------------------- | ----------- | --------------------- | -------------------- | ----------------------------------- |
| `back_up_to_dynamic: true`  | Required    | Encrypted copy stored | **Required**         | `run_recover_key_shares` + password |
| `back_up_to_dynamic: false` | Required    | None                  | Optional             | None — share loss = wallet loss     |

<Warning>
  Don't reuse a single password across all wallets — derive one per wallet from a KMS-wrapped secret. A leaked password + leaked `walletId` lets an attacker decrypt the share from Dynamic's backup.
</Warning>

## Step 3: Create Your First Wallet

Here's a complete example of creating an EVM wallet:

```rust theme={"system"}
use dynamic_waas_sdk::{
    DynamicWalletClient, DynamicWalletClientOpts, ServerKeyShare,
    ThresholdSignatureScheme, WalletProperties,
};
use dynamic_waas_sdk_evm::DynamicEvmWalletClient;

pub async fn authenticated_client(
    env_id: &str,
    api_token: &str,
) -> dynamic_waas_sdk::Result<DynamicWalletClient> {
    let mut client = DynamicWalletClient::new(
        DynamicWalletClientOpts::new(env_id),
    )?;
    client.authenticate_api_token(api_token).await?;
    Ok(client)
}

pub async fn create_evm_wallet(
    client: &DynamicWalletClient,
    threshold_signature_scheme: ThresholdSignatureScheme,
    password: String, // required when back_up_to_dynamic = true
) -> dynamic_waas_sdk::Result<(WalletProperties, Vec<ServerKeyShare>)> {
    let evm = DynamicEvmWalletClient::new(client);

    evm.create_wallet_account(
        threshold_signature_scheme,
        Some(password),
        /* back_up_to_dynamic */ true,
    )
    .await
}

// Usage
let client = authenticated_client(&env_id, &api_token).await?;
let (wallet_properties, external_server_key_shares) = create_evm_wallet(
    &client,
    ThresholdSignatureScheme::TwoOfTwo,
    "your-secure-password".to_string(),
).await?;

println!("Wallet created: {}", wallet_properties.account_address);
```

## Step 4: Handle Errors

The SDK returns `dynamic_waas_sdk::Error`. Match on the variants you care about:

```rust theme={"system"}
use dynamic_waas_sdk::Error;

match create_evm_wallet(&client, ThresholdSignatureScheme::TwoOfTwo, password).await {
    Ok((wp, _shares)) => println!("Wallet created: {}", wp.account_address),
    Err(Error::InvalidArgument(msg)) if msg.contains("password") => {
        eprintln!("Password is required when backing up to Dynamic");
    }
    Err(Error::Auth(_)) => {
        eprintln!("Invalid session — re-authenticate with authenticate_api_token");
    }
    Err(e) => eprintln!("Wallet creation failed: {e:?}"),
}
```

## Step 5: Persist `WalletProperties` and `Vec<ServerKeyShare>`

`create_wallet_account()` returns two pieces of state — each belongs in a different storage tier:

```rust theme={"system"}
let (wallet_properties, external_server_key_shares) = evm
    .create_wallet_account(
        ThresholdSignatureScheme::TwoOfTwo,
        Some("your-secure-password".to_string()),
        /* back_up_to_dynamic */ true,
    )
    .await?;

// WalletProperties — non-sensitive identity + backup-pointer info. Cache it.
redis.set(
    format!("wallet:{}", wallet_properties.account_address),
    serde_json::to_string(&wallet_properties)?,
).await?;

// Vec<ServerKeyShare> — sensitive MPC key material. Vault it.
vault.write(
    format!("wallet:{}/shares", wallet_properties.account_address),
    serde_json::to_vec(&external_server_key_shares)?,
).await?;
```

The SDK is stateless and you must pass `WalletProperties` to every subsequent sign / export operation. See [Storage Best Practices](/rust/storage-best-practices) for the full pattern.

## Best Practices

1. **Password Security** — use strong, unique passwords per wallet; never log them
2. **Error Handling** — match on `dynamic_waas_sdk::Error` variants rather than string-matching
3. **Tracing** — the SDK uses `tracing::instrument` and `skip`s sensitive args; mirror that in your code
4. **Backup Strategy** — if `back_up_to_dynamic: false`, persist shares to a vault before returning success to the caller

## Next Steps

Now that you've created a wallet, you can:

* [Sign messages](/rust/evm/sign-messages)
* [Export the private key](/rust/evm/export-private-key)
* [Use delegated access](/rust/evm/delegated-access)
