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

# Generate a Wallet

> Create new Ethereum wallets from mnemonic phrases

<Info>
  **Skill** — Copyable reference implementation. Use as-is or customize. See [Skills Philosophy](/concepts/skills).
</Info>

## Overview

Generate Ethereum wallets using BIP-39 mnemonics and BIP-32/BIP-44 hierarchical deterministic key derivation. This guide covers the complete workflow from mnemonic generation to Ethereum address derivation.

## Quick Start

```typescript theme={null}
import * as Bip39 from '@voltaire/crypto/Bip39';
import * as HDWallet from '@voltaire/crypto/HDWallet';
import * as Secp256k1 from '@voltaire/crypto/Secp256k1';
import { Address } from '@voltaire/primitives/Address';

// 1. Generate a 24-word mnemonic
const mnemonic = Bip39.generateMnemonic(256);
console.log('Backup this mnemonic:', mnemonic);

// 2. Derive seed from mnemonic
const seed = await Bip39.mnemonicToSeed(mnemonic);

// 3. Create HD wallet root key
const root = HDWallet.fromSeed(seed);

// 4. Derive first Ethereum account (m/44'/60'/0'/0/0)
const account = HDWallet.deriveEthereum(root, 0, 0);

// 5. Get private key
const privateKey = HDWallet.getPrivateKey(account);

// 6. Derive Ethereum address
const publicKey = Secp256k1.derivePublicKey(privateKey);
const address = Address.fromPublicKey(publicKey);

console.log('Address:', address.toHex());
```

## Generate Mnemonic

BIP-39 mnemonics provide human-readable backup for wallet seeds.

### 12-Word Mnemonic (128 bits)

```typescript theme={null}
import * as Bip39 from '@voltaire/crypto/Bip39';

// 128 bits = 12 words
const mnemonic12 = Bip39.generateMnemonic(128);
console.log(mnemonic12);
// "abandon ability able about above absent absorb abstract absurd abuse access accident"
```

### 24-Word Mnemonic (256 bits, recommended)

```typescript theme={null}
// 256 bits = 24 words (maximum security)
const mnemonic24 = Bip39.generateMnemonic(256);
console.log(mnemonic24);
// "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art"
```

### Entropy to Word Count

| Entropy Bits | Words | Security Level |
| ------------ | ----- | -------------- |
| 128          | 12    | Standard       |
| 160          | 15    | Enhanced       |
| 192          | 18    | High           |
| 224          | 21    | Very High      |
| 256          | 24    | Maximum        |

## Derive Seed from Mnemonic

Convert mnemonic to 64-byte seed using PBKDF2-HMAC-SHA512.

### Async Derivation

```typescript theme={null}
import * as Bip39 from '@voltaire/crypto/Bip39';

const mnemonic = 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about';

// Without passphrase
const seed = await Bip39.mnemonicToSeed(mnemonic);
console.log(seed.length); // 64

// With passphrase (adds extra security)
const seedWithPass = await Bip39.mnemonicToSeed(mnemonic, 'my secret passphrase');
// Different seed than without passphrase
```

### Sync Derivation

```typescript theme={null}
// Synchronous version (blocks execution)
const seed = Bip39.mnemonicToSeedSync(mnemonic);
console.log(seed.length); // 64
```

## Create HD Wallet

Create hierarchical deterministic wallet from seed.

```typescript theme={null}
import * as Bip39 from '@voltaire/crypto/Bip39';
import * as HDWallet from '@voltaire/crypto/HDWallet';

const mnemonic = Bip39.generateMnemonic(256);
const seed = await Bip39.mnemonicToSeed(mnemonic);

// Create root HD key
const root = HDWallet.fromSeed(seed);

// Export extended keys for backup/recovery
const xprv = HDWallet.toExtendedPrivateKey(root);
const xpub = HDWallet.toExtendedPublicKey(root);

console.log(xprv); // "xprv9s21ZrQH143K..."
console.log(xpub); // "xpub661MyMwAqRbcF..."
```

## Derive Ethereum Accounts

Use BIP-44 path `m/44'/60'/account'/0/index` for Ethereum.

### Single Account

```typescript theme={null}
import * as HDWallet from '@voltaire/crypto/HDWallet';

// Derive first Ethereum address (account 0, index 0)
const eth0 = HDWallet.deriveEthereum(root, 0, 0);

// Get private key (32 bytes)
const privateKey = HDWallet.getPrivateKey(eth0);
console.log(privateKey.length); // 32

// Get compressed public key (33 bytes)
const publicKeyCompressed = HDWallet.getPublicKey(eth0);
console.log(publicKeyCompressed.length); // 33
```

### Multiple Addresses

```typescript theme={null}
// Derive multiple addresses from same account
const addresses = [];

for (let i = 0; i < 5; i++) {
  const key = HDWallet.deriveEthereum(root, 0, i);
  const privateKey = HDWallet.getPrivateKey(key);
  addresses.push({
    path: `m/44'/60'/0'/0/${i}`,
    privateKey
  });
}

console.log(`Derived ${addresses.length} addresses`);
```

### Multiple Accounts

```typescript theme={null}
// Derive from different accounts
const account0 = HDWallet.deriveEthereum(root, 0, 0); // m/44'/60'/0'/0/0
const account1 = HDWallet.deriveEthereum(root, 1, 0); // m/44'/60'/1'/0/0
const account2 = HDWallet.deriveEthereum(root, 2, 0); // m/44'/60'/2'/0/0
```

## Get Ethereum Address

Convert private key to Ethereum address.

```typescript theme={null}
import * as Secp256k1 from '@voltaire/crypto/Secp256k1';
import { Address } from '@voltaire/primitives/Address';

// Get private key from HD derivation
const privateKey = HDWallet.getPrivateKey(eth0);

// Derive uncompressed public key (64 bytes)
const publicKey = Secp256k1.derivePublicKey(privateKey);
console.log(publicKey.length); // 64

// Create Ethereum address from public key
const address = Address.fromPublicKey(publicKey);
console.log(address.toHex()); // "0x9858EfFD232B4033E47d90003D41EC34EcaEda94"
```

## Import Existing Mnemonic

Restore wallet from backed-up mnemonic.

```typescript theme={null}
import * as Bip39 from '@voltaire/crypto/Bip39';
import * as HDWallet from '@voltaire/crypto/HDWallet';
import * as Secp256k1 from '@voltaire/crypto/Secp256k1';
import { Address } from '@voltaire/primitives/Address';

// User provides backed-up mnemonic
const mnemonic = 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about';

// Validate mnemonic first
if (!Bip39.validateMnemonic(mnemonic)) {
  throw new Error('Invalid mnemonic');
}

// Restore wallet (use same passphrase if one was used)
const seed = await Bip39.mnemonicToSeed(mnemonic);
const root = HDWallet.fromSeed(seed);

// Derive same addresses as before
const eth0 = HDWallet.deriveEthereum(root, 0, 0);
const privateKey = HDWallet.getPrivateKey(eth0);
const publicKey = Secp256k1.derivePublicKey(privateKey);
const address = Address.fromPublicKey(publicKey);

console.log('Restored address:', address.toHex());
```

## Import from Extended Key

Restore from xprv/xpub string.

```typescript theme={null}
import * as HDWallet from '@voltaire/crypto/HDWallet';

// From extended private key (full access)
const xprv = 'xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi';
const key = HDWallet.fromExtendedKey(xprv);

// Can derive any child (hardened or normal)
const child = HDWallet.derivePath(key, "m/44'/60'/0'/0/0");

// From extended public key (watch-only)
const xpub = 'xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8';
const pubOnly = HDWallet.fromPublicExtendedKey(xpub);

// Can only derive non-hardened children
const watchAddress = HDWallet.deriveChild(pubOnly, 0);
console.log(HDWallet.getPrivateKey(watchAddress)); // null (no private key)
console.log(HDWallet.getPublicKey(watchAddress));  // Uint8Array(33)
```

## Custom Derivation Paths

Derive keys using any BIP-32 path.

```typescript theme={null}
import * as HDWallet from '@voltaire/crypto/HDWallet';

// Standard Ethereum path
const eth = HDWallet.derivePath(root, "m/44'/60'/0'/0/0");

// Bitcoin path
const btc = HDWallet.derivePath(root, "m/44'/0'/0'/0/0");

// Custom path
const custom = HDWallet.derivePath(root, "m/0'/1/2'/3");

// Path validation
console.log(HDWallet.isValidPath("m/44'/60'/0'/0/0")); // true
console.log(HDWallet.isValidPath("invalid/path"));     // false

// Check for hardened derivation
console.log(HDWallet.isHardenedPath("m/44'/60'/0'")); // true
console.log(HDWallet.isHardenedPath("m/44/60/0"));    // false
```

## Complete Wallet Class Example

```typescript theme={null}
import * as Bip39 from '@voltaire/crypto/Bip39';
import * as HDWallet from '@voltaire/crypto/HDWallet';
import * as Secp256k1 from '@voltaire/crypto/Secp256k1';
import { Address } from '@voltaire/primitives/Address';

class Wallet {
  private root: ReturnType<typeof HDWallet.fromSeed>;

  private constructor(root: ReturnType<typeof HDWallet.fromSeed>) {
    this.root = root;
  }

  static async create(): Promise<Wallet> {
    const mnemonic = Bip39.generateMnemonic(256);
    const seed = await Bip39.mnemonicToSeed(mnemonic);
    console.log('BACKUP YOUR MNEMONIC:', mnemonic);
    return new Wallet(HDWallet.fromSeed(seed));
  }

  static async fromMnemonic(mnemonic: string, passphrase = ''): Promise<Wallet> {
    if (!Bip39.validateMnemonic(mnemonic)) {
      throw new Error('Invalid mnemonic');
    }
    const seed = await Bip39.mnemonicToSeed(mnemonic, passphrase);
    return new Wallet(HDWallet.fromSeed(seed));
  }

  static fromExtendedKey(xprv: string): Wallet {
    return new Wallet(HDWallet.fromExtendedKey(xprv));
  }

  getAccount(accountIndex: number, addressIndex: number = 0) {
    const key = HDWallet.deriveEthereum(this.root, accountIndex, addressIndex);
    const privateKey = HDWallet.getPrivateKey(key)!;
    const publicKey = Secp256k1.derivePublicKey(privateKey);
    const address = Address.fromPublicKey(publicKey);

    return {
      path: `m/44'/60'/${accountIndex}'/0/${addressIndex}`,
      privateKey,
      publicKey,
      address: address.toHex()
    };
  }

  getAccounts(count: number, accountIndex: number = 0) {
    return Array.from({ length: count }, (_, i) =>
      this.getAccount(accountIndex, i)
    );
  }

  exportExtendedPrivateKey(): string {
    return HDWallet.toExtendedPrivateKey(this.root);
  }

  exportExtendedPublicKey(): string {
    return HDWallet.toExtendedPublicKey(this.root);
  }
}

// Usage
const wallet = await Wallet.create();
const account = wallet.getAccount(0, 0);
console.log('Address:', account.address);

// Restore from mnemonic
const restored = await Wallet.fromMnemonic(
  'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about'
);
console.log('Restored:', restored.getAccount(0, 0).address);
```

## Security Best Practices

### Entropy Quality

```typescript theme={null}
// Always use Bip39.generateMnemonic() - uses crypto.getRandomValues()
const secure = Bip39.generateMnemonic(256);

// NEVER use Math.random() or predictable sources
```

### Passphrase Usage

```typescript theme={null}
// Passphrase adds extra security layer
const seed = await Bip39.mnemonicToSeed(mnemonic, 'strong passphrase');

// Warning: Forgetting passphrase = permanent loss
// Different passphrase = completely different wallet
```

### Memory Handling

```typescript theme={null}
// Clear sensitive data after use
function clearKey(key: Uint8Array) {
  key.fill(0);
}

const privateKey = HDWallet.getPrivateKey(account);
// ... use privateKey ...
clearKey(privateKey); // Zero out when done
```

### Storage Guidelines

* **Mnemonic**: Write on paper, store in fireproof safe, never digital
* **Passphrase**: Memorize or store separately from mnemonic
* **xprv**: Treat like private key, never transmit unencrypted
* **xpub**: Safe to share for watch-only access

## API Reference

### Bip39 Functions

| Function                                    | Description                                  |
| ------------------------------------------- | -------------------------------------------- |
| `generateMnemonic(bits)`                    | Generate mnemonic (128/160/192/224/256 bits) |
| `validateMnemonic(mnemonic)`                | Check if mnemonic is valid BIP-39            |
| `mnemonicToSeed(mnemonic, passphrase?)`     | Async seed derivation                        |
| `mnemonicToSeedSync(mnemonic, passphrase?)` | Sync seed derivation                         |

### HDWallet Functions

| Function                              | Description                       |
| ------------------------------------- | --------------------------------- |
| `fromSeed(seed)`                      | Create root key from 64-byte seed |
| `fromExtendedKey(xprv)`               | Import from extended private key  |
| `fromPublicExtendedKey(xpub)`         | Import from extended public key   |
| `derivePath(key, path)`               | Derive child by BIP-32 path       |
| `deriveChild(key, index)`             | Derive child by index             |
| `deriveEthereum(key, account, index)` | Derive Ethereum address           |
| `getPrivateKey(key)`                  | Get 32-byte private key           |
| `getPublicKey(key)`                   | Get 33-byte compressed public key |
| `toExtendedPrivateKey(key)`           | Export xprv string                |
| `toExtendedPublicKey(key)`            | Export xpub string                |

### Address Functions

| Function                          | Description                                         |
| --------------------------------- | --------------------------------------------------- |
| `Address.fromPublicKey(pubKey)`   | Create address from 64-byte uncompressed public key |
| `Address.fromPrivateKey(privKey)` | Create address from 32-byte private key             |
| `address.toHex()`                 | Get checksummed hex string                          |

## References

* [BIP-39: Mnemonic code for generating deterministic keys](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki)
* [BIP-32: Hierarchical Deterministic Wallets](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki)
* [BIP-44: Multi-Account Hierarchy](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki)
* [SLIP-44: Coin Type Registry](https://github.com/satoshilabs/slips/blob/master/slip-0044.md)
