|
| 1 | +//! Comprehensive example of BIP39 mnemonic seed phrase support for Mina |
| 2 | +//! |
| 3 | +//! This example demonstrates: |
| 4 | +//! 1. Generating BIP39 mnemonic phrases |
| 5 | +//! 2. Deriving Mina keypairs from mnemonics |
| 6 | +//! 3. Using BIP32 hierarchical deterministic derivation (Ledger-compatible) |
| 7 | +//! 4. Deriving multiple accounts from a single mnemonic |
| 8 | +//! |
| 9 | +//! Run with: |
| 10 | +//! ``` |
| 11 | +//! cargo run --example bip39_derivation |
| 12 | +//! ``` |
| 13 | +
|
| 14 | +use mina_signer::bip39::{Bip39, MINA_COIN_TYPE}; |
| 15 | + |
| 16 | +fn main() -> Result<(), Box<dyn std::error::Error>> { |
| 17 | + println!("=== Mina BIP39 Derivation Example ===\n"); |
| 18 | + |
| 19 | + // Example 1: Generate a new mnemonic |
| 20 | + println!("1. Generate a new 24-word mnemonic:"); |
| 21 | + let mnemonic = Bip39::generate_mnemonic(24)?; |
| 22 | + println!(" Mnemonic: {}\n", mnemonic); |
| 23 | + |
| 24 | + // Example 2: Use a known test mnemonic |
| 25 | + let test_mnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"; |
| 26 | + println!("2. Using test mnemonic for reproducible results:"); |
| 27 | + println!(" Mnemonic: {}\n", test_mnemonic); |
| 28 | + |
| 29 | + // Example 3: Simple derivation (non-BIP32) |
| 30 | + println!("3. Simple derivation (non-BIP32 hierarchical):"); |
| 31 | + let keypair_simple = Bip39::mnemonic_to_keypair(test_mnemonic, None)?; |
| 32 | + println!(" Secret key: {}", keypair_simple.secret.to_hex()); |
| 33 | + println!(" Address: {}\n", keypair_simple.public.into_address()); |
| 34 | + |
| 35 | + // Example 4: BIP32 hierarchical derivation (Ledger-compatible) |
| 36 | + println!("4. BIP32 hierarchical derivation (Ledger-compatible):"); |
| 37 | + println!(" Path: m/44'/{}'/<account>'/0/0", MINA_COIN_TYPE); |
| 38 | + let keypair_bip32 = Bip39::mnemonic_to_keypair_bip32(test_mnemonic, None, 0)?; |
| 39 | + println!(" Account 0:"); |
| 40 | + println!(" Secret key: {}", keypair_bip32.secret.to_hex()); |
| 41 | + println!(" Address: {}\n", keypair_bip32.public.into_address()); |
| 42 | + |
| 43 | + // Example 5: Multiple accounts from the same mnemonic |
| 44 | + println!("5. Derive multiple accounts (BIP32 HD wallet):"); |
| 45 | + for account in 0..3 { |
| 46 | + let keypair = Bip39::mnemonic_to_keypair_bip32(test_mnemonic, None, account)?; |
| 47 | + println!(" Account {}: {}", account, keypair.public.into_address()); |
| 48 | + } |
| 49 | + println!(); |
| 50 | + |
| 51 | + // Example 6: Using a passphrase for additional security |
| 52 | + println!("6. Derivation with optional passphrase:"); |
| 53 | + let keypair_no_pass = Bip39::mnemonic_to_keypair_bip32(test_mnemonic, None, 0)?; |
| 54 | + let keypair_with_pass = |
| 55 | + Bip39::mnemonic_to_keypair_bip32(test_mnemonic, Some("my-secret-passphrase"), 0)?; |
| 56 | + |
| 57 | + println!( |
| 58 | + " Without passphrase: {}", |
| 59 | + keypair_no_pass.public.into_address() |
| 60 | + ); |
| 61 | + println!( |
| 62 | + " With passphrase: {}", |
| 63 | + keypair_with_pass.public.into_address() |
| 64 | + ); |
| 65 | + println!(" (Different passphrases produce different keys)\n"); |
| 66 | + |
| 67 | + // Example 7: Working with seeds directly |
| 68 | + println!("7. Advanced: Working with seeds directly:"); |
| 69 | + let seed = Bip39::mnemonic_to_seed(test_mnemonic, None)?; |
| 70 | + println!(" Seed length: {} bytes", seed.len()); |
| 71 | + println!(" Seed (hex): {}...", hex::encode(&seed[..16])); |
| 72 | + |
| 73 | + // Derive from seed |
| 74 | + let keypair_from_seed = Bip39::seed_to_keypair_bip32(&seed, 0)?; |
| 75 | + println!( |
| 76 | + " Derived address: {}\n", |
| 77 | + keypair_from_seed.public.into_address() |
| 78 | + ); |
| 79 | + |
| 80 | + // Example 8: Non-BIP32 account indexing |
| 81 | + println!("8. Simple account indexing (non-BIP32):"); |
| 82 | + for account_index in 0..3 { |
| 83 | + let keypair = Bip39::mnemonic_to_keypair_with_index(test_mnemonic, None, account_index)?; |
| 84 | + println!( |
| 85 | + " Account {}: {}", |
| 86 | + account_index, |
| 87 | + keypair.public.into_address() |
| 88 | + ); |
| 89 | + } |
| 90 | + |
| 91 | + println!("\n=== Best Practices ==="); |
| 92 | + println!("1. Use BIP32 derivation (mnemonic_to_keypair_bip32) for Ledger compatibility"); |
| 93 | + println!("2. Store mnemonics securely - they provide access to all derived accounts"); |
| 94 | + println!("3. Use passphrases for an additional layer of security"); |
| 95 | + println!("4. BIP44 path for Mina: m/44'/12586'/<account>'/0/0"); |
| 96 | + println!("5. Never share your mnemonic or secret keys"); |
| 97 | + |
| 98 | + Ok(()) |
| 99 | +} |
0 commit comments