<100 subscribers
<100 subscribers
Share Dialog
Share Dialog
When you open a crypto wallet—whether it’s MetaMask, Phantom, or even your own Custom CLI (like I built this one)—the experience feels almost effortless: one seed phrase, one wallet, and suddenly an endless list of accounts and addresses spanning multiple blockchains. But behind that simplicity is a beautifully engineered foundation of standards—especially BIP-32, BIP-39, and BIP-44—that work together to deterministically generate keys and keep the entire wallet ecosystem interoperable, recoverable, and consistent.
This post walks through that journey in a clear, step-by-step narrative, explaining how BIP-32, BIP-39, and BIP-44 form the backbone of nearly every modern wallet—whether you’re dealing with Bitcoin, Ethereum, Solana, or any chain built on hierarchical deterministic (HD) wallets.
If you’re building your first wallet or simply want to understand what really happens under the hood each time you click “Create Wallet,” this guide will walk you through the entire process.
In the early days of Bitcoin, wallets generated random private keys for every address.
Problems were immediate:
Every new keypair had to be stored manually
Losing the wallet file meant losing funds
No standard way to back up or restore keys
No connection between keys—each was an isolated identity
There was no structure, no hierarchy, and no recoverability. Clearly unsustainable.
This is where the BIPs stepped in.
BIP-32 introduced the HD (Hierarchical Deterministic) wallet.
Core idea:
From one master seed, generate a tree of keys deterministically.
Benefits:
Single backup → infinite keys
Parent → child key derivation
Organized accounts and subaccounts
No need to store every private key
The tree looks like:
m
├─ 44′ (purpose)
├─ 0′ (Bitcoin)
│ ├─ 0′ (Account 0)
│ │ ├─ 0 (Addr 0)
│ │ ├─ 1 (Addr 1)
│ ├─ 1′ (Account 1)
│ ├─ 0 (Addr 0)
│ ├─ 1 (Addr 1)
├─ 60′ (Ethereum)
│ ├─ 0′ (Account 0)
│ │ ├─ 0 (Addr 0)
│ │ ├─ 1 (Addr 1)
│ ├─ 1′ (Account 1)
│ ├─ 0 (Addr 0)
│ ├─ 1 (Addr 1)
├─ 501′ (Solana)
├─ 0′ (Account 0)
│ ├─ 0 (Addr 0)
│ ├─ 1 (Addr 1)
├─ 1′ (Account 1)
├─ 0 (Addr 0)
├─ 1 (Addr 1)
Every wallet today—whether it's Bitcoin, Ethereum, or Solana—builds on this principle.
A 512-bit seed is not user-friendly. Humans needed a safe way to back up their HD wallets.
BIP-39 solved this by introducing:
12/18/24-word mnemonic phrases
Deterministic entropy → mnemonic mapping
Multi-language wordlists
Mnemonic → seed via PBKDF2
Example:
abandon amount liar ... zoo
This mnemonic is the only thing a user needs to restore all their accounts and addresses.
With HD wallets and mnemonics established, the next challenge was consistency across:
Multiple accounts
Multiple chains
External vs internal addresses
BIP-44 provided a universal path structure:
m / purpose' / coin_type' / account' / change / address_index
Example derivation paths:
Chain BIP-44 Path
Bitcoin m/44'/0'/0'/0/0 (Legacy)
Bitcoin m/84'/0'/0'/0/0 (Native SegWit)
Ethereum m/44'/60'/0'/0/0
Solana m/44'/501'/0'/0'
This standardization enables a single mnemonic to power wallets across multiple chains.
BIP-44 brought order to the ecosystem.
Here's the entire flow in one place:
User writes down mnemonic (BIP-39)
↓
Mnemonic → Seed (PBKDF2)
↓
Seed → Master Private Key + Chain Code (BIP-32)
↓
Use the derivation path to derive the child key (BIP-44)
↓
Chain-specific private key → Public key
↓
Public key → Address
No private key or address is ever random. Everything is deterministic, organized, and reproducible from the mnemonic.
import bip39 from "bip39";
import BIP32Factory from "bip32";
import * as ecc from "tiny-secp256k1";
import { payments, networks } from "bitcoinjs-lib";
// Generate 128 bits of entropy → 12 words
const mnemonic = bip39.generateMnemonic(128);
console.log("Mnemonic:", mnemonic);
// Convert mnemonic → seed (64 bytes)
const seed = await bip39.mnemonicToSeed(mnemonic);
// Get root from Seed Buffer
const bip32 = BIP32Factory(ecc);
const root = bip32.fromSeed(seed);
const btcPath = `m/84'/0'/0'/0/0`; // Native SegWit
const btcChild = root.derivePath(btcPath);
// BTC Address (SegWit)
const btcAddress = payments.p2wpkh({
pubkey: btcChild.publicKey,
network: networks.bitcoin
}).address;import bip39 from "bip39";
import BIP32Factory from "bip32";
import * as ecc from "tiny-secp256k1";
import { ethers } from "ethers";
// Generate 128 bits of entropy → 12 words
const mnemonic = bip39.generateMnemonic(128);
console.log("Mnemonic:", mnemonic);
// Convert mnemonic → seed (64 bytes)
const seed = await bip39.mnemonicToSeed(mnemonic);
// Get root from Seed Buffer
const bip32 = BIP32Factory(ecc);
const root = bip32.fromSeed(seed);
const ethPath = `m/44'/60'/0'/0/0`;
const ethChild = root.derivePath(ethPath);
const ethPriv = ethers.hexlify(ethChild.privateKey);
const ethWallet = new ethers.Wallet(ethPriv);
// ETH Address
const ethAddress = ethWallet.address;
import bip39 from "bip39";
import BIP32Factory from "bip32";
import * as ecc from "tiny-secp256k1";
import nacl from "tweetnacl";
import bs58 from "bs58";
import { derivePath as deriveEd25519 } from "ed25519-hd-key";
import { PublicKey } from "@solana/web3.js";
// Generate 128 bits of entropy → 12 words
const mnemonic = bip39.generateMnemonic(128);
console.log("Mnemonic:", mnemonic);
// Convert mnemonic → seed (64 bytes)
const seed = await bip39.mnemonicToSeed(mnemonic);
// Get root from Seed Buffer
const bip32 = BIP32Factory(ecc);
const root = bip32.fromSeed(seed);
const solPath = `m/44'/501'/0'/0'`;
const solDerived = deriveEd25519(solPath, seed.toString("hex"));
const solKeypair = nacl.sign.keyPair.fromSeed(solDerived.key);
const solPrivateKey = bs58.encode(solKeypair.secretKey);
const solPubKey = new PublicKey(solKeypair.publicKey).toBase58()
// SOL Address
const solAddress = solPubKey;
While BIPs come from Bitcoin, other ecosystems adopted them with small variations:
Ethereum
Still uses BIP-39 and BIP-44
Uses secp256k1 keys
Address = last 20 bytes of keccak(publicKey)
Solana
BIP-39 and BIP-44 for mnemonic + path
Uses ed25519 keys
Different signing scheme
The seed → key → address pipeline remains the same. Only the last step changes per chain.
Every time a wallet displays a new address, switches networks, or allows you to create Account #2, it's the result of years of standards working together perfectly.
The magic formula:
BIP-32 → Deterministic key trees
BIP-39 → Human-readable mnemonics
BIP-44 → Organized multichain structure
Understanding these standards is the first step for any developer building wallet software, exploring Web3 security, or simply becoming a more informed user.
If you're starting your wallet journey, the best way to learn is to implement these pieces yourself—generate a mnemonic, derive the seed, apply a derivation path, and produce an address. Everything else becomes much clearer from there.
I tried with npx new-wallet.
When you open a crypto wallet—whether it’s MetaMask, Phantom, or even your own Custom CLI (like I built this one)—the experience feels almost effortless: one seed phrase, one wallet, and suddenly an endless list of accounts and addresses spanning multiple blockchains. But behind that simplicity is a beautifully engineered foundation of standards—especially BIP-32, BIP-39, and BIP-44—that work together to deterministically generate keys and keep the entire wallet ecosystem interoperable, recoverable, and consistent.
This post walks through that journey in a clear, step-by-step narrative, explaining how BIP-32, BIP-39, and BIP-44 form the backbone of nearly every modern wallet—whether you’re dealing with Bitcoin, Ethereum, Solana, or any chain built on hierarchical deterministic (HD) wallets.
If you’re building your first wallet or simply want to understand what really happens under the hood each time you click “Create Wallet,” this guide will walk you through the entire process.
In the early days of Bitcoin, wallets generated random private keys for every address.
Problems were immediate:
Every new keypair had to be stored manually
Losing the wallet file meant losing funds
No standard way to back up or restore keys
No connection between keys—each was an isolated identity
There was no structure, no hierarchy, and no recoverability. Clearly unsustainable.
This is where the BIPs stepped in.
BIP-32 introduced the HD (Hierarchical Deterministic) wallet.
Core idea:
From one master seed, generate a tree of keys deterministically.
Benefits:
Single backup → infinite keys
Parent → child key derivation
Organized accounts and subaccounts
No need to store every private key
The tree looks like:
m
├─ 44′ (purpose)
├─ 0′ (Bitcoin)
│ ├─ 0′ (Account 0)
│ │ ├─ 0 (Addr 0)
│ │ ├─ 1 (Addr 1)
│ ├─ 1′ (Account 1)
│ ├─ 0 (Addr 0)
│ ├─ 1 (Addr 1)
├─ 60′ (Ethereum)
│ ├─ 0′ (Account 0)
│ │ ├─ 0 (Addr 0)
│ │ ├─ 1 (Addr 1)
│ ├─ 1′ (Account 1)
│ ├─ 0 (Addr 0)
│ ├─ 1 (Addr 1)
├─ 501′ (Solana)
├─ 0′ (Account 0)
│ ├─ 0 (Addr 0)
│ ├─ 1 (Addr 1)
├─ 1′ (Account 1)
├─ 0 (Addr 0)
├─ 1 (Addr 1)
Every wallet today—whether it's Bitcoin, Ethereum, or Solana—builds on this principle.
A 512-bit seed is not user-friendly. Humans needed a safe way to back up their HD wallets.
BIP-39 solved this by introducing:
12/18/24-word mnemonic phrases
Deterministic entropy → mnemonic mapping
Multi-language wordlists
Mnemonic → seed via PBKDF2
Example:
abandon amount liar ... zoo
This mnemonic is the only thing a user needs to restore all their accounts and addresses.
With HD wallets and mnemonics established, the next challenge was consistency across:
Multiple accounts
Multiple chains
External vs internal addresses
BIP-44 provided a universal path structure:
m / purpose' / coin_type' / account' / change / address_index
Example derivation paths:
Chain BIP-44 Path
Bitcoin m/44'/0'/0'/0/0 (Legacy)
Bitcoin m/84'/0'/0'/0/0 (Native SegWit)
Ethereum m/44'/60'/0'/0/0
Solana m/44'/501'/0'/0'
This standardization enables a single mnemonic to power wallets across multiple chains.
BIP-44 brought order to the ecosystem.
Here's the entire flow in one place:
User writes down mnemonic (BIP-39)
↓
Mnemonic → Seed (PBKDF2)
↓
Seed → Master Private Key + Chain Code (BIP-32)
↓
Use the derivation path to derive the child key (BIP-44)
↓
Chain-specific private key → Public key
↓
Public key → Address
No private key or address is ever random. Everything is deterministic, organized, and reproducible from the mnemonic.
import bip39 from "bip39";
import BIP32Factory from "bip32";
import * as ecc from "tiny-secp256k1";
import { payments, networks } from "bitcoinjs-lib";
// Generate 128 bits of entropy → 12 words
const mnemonic = bip39.generateMnemonic(128);
console.log("Mnemonic:", mnemonic);
// Convert mnemonic → seed (64 bytes)
const seed = await bip39.mnemonicToSeed(mnemonic);
// Get root from Seed Buffer
const bip32 = BIP32Factory(ecc);
const root = bip32.fromSeed(seed);
const btcPath = `m/84'/0'/0'/0/0`; // Native SegWit
const btcChild = root.derivePath(btcPath);
// BTC Address (SegWit)
const btcAddress = payments.p2wpkh({
pubkey: btcChild.publicKey,
network: networks.bitcoin
}).address;import bip39 from "bip39";
import BIP32Factory from "bip32";
import * as ecc from "tiny-secp256k1";
import { ethers } from "ethers";
// Generate 128 bits of entropy → 12 words
const mnemonic = bip39.generateMnemonic(128);
console.log("Mnemonic:", mnemonic);
// Convert mnemonic → seed (64 bytes)
const seed = await bip39.mnemonicToSeed(mnemonic);
// Get root from Seed Buffer
const bip32 = BIP32Factory(ecc);
const root = bip32.fromSeed(seed);
const ethPath = `m/44'/60'/0'/0/0`;
const ethChild = root.derivePath(ethPath);
const ethPriv = ethers.hexlify(ethChild.privateKey);
const ethWallet = new ethers.Wallet(ethPriv);
// ETH Address
const ethAddress = ethWallet.address;
import bip39 from "bip39";
import BIP32Factory from "bip32";
import * as ecc from "tiny-secp256k1";
import nacl from "tweetnacl";
import bs58 from "bs58";
import { derivePath as deriveEd25519 } from "ed25519-hd-key";
import { PublicKey } from "@solana/web3.js";
// Generate 128 bits of entropy → 12 words
const mnemonic = bip39.generateMnemonic(128);
console.log("Mnemonic:", mnemonic);
// Convert mnemonic → seed (64 bytes)
const seed = await bip39.mnemonicToSeed(mnemonic);
// Get root from Seed Buffer
const bip32 = BIP32Factory(ecc);
const root = bip32.fromSeed(seed);
const solPath = `m/44'/501'/0'/0'`;
const solDerived = deriveEd25519(solPath, seed.toString("hex"));
const solKeypair = nacl.sign.keyPair.fromSeed(solDerived.key);
const solPrivateKey = bs58.encode(solKeypair.secretKey);
const solPubKey = new PublicKey(solKeypair.publicKey).toBase58()
// SOL Address
const solAddress = solPubKey;
While BIPs come from Bitcoin, other ecosystems adopted them with small variations:
Ethereum
Still uses BIP-39 and BIP-44
Uses secp256k1 keys
Address = last 20 bytes of keccak(publicKey)
Solana
BIP-39 and BIP-44 for mnemonic + path
Uses ed25519 keys
Different signing scheme
The seed → key → address pipeline remains the same. Only the last step changes per chain.
Every time a wallet displays a new address, switches networks, or allows you to create Account #2, it's the result of years of standards working together perfectly.
The magic formula:
BIP-32 → Deterministic key trees
BIP-39 → Human-readable mnemonics
BIP-44 → Organized multichain structure
Understanding these standards is the first step for any developer building wallet software, exploring Web3 security, or simply becoming a more informed user.
If you're starting your wallet journey, the best way to learn is to implement these pieces yourself—generate a mnemonic, derive the seed, apply a derivation path, and produce an address. Everything else becomes much clearer from there.
I tried with npx new-wallet.
No comments yet