How to Build a Crypto Wallet From Scratch

Building a crypto wallet means writing software that can generate cryptographic key pairs, derive addresses from those keys, and sign transactions that get broadcast to a blockchain network. Whether you’re building a simple command-line tool for personal use or a full-featured app, the core architecture follows well-established standards and relies on open-source libraries that handle the heavy cryptographic lifting. Here’s what goes into it, from key generation to connecting with a live blockchain.

How Wallet Key Generation Works

Every crypto wallet starts with a private key, a long random number that gives its holder the ability to sign transactions and move funds. The corresponding public key (and the wallet address derived from it) is what other people use to send you crypto. Generating and managing these keys correctly is the single most important part of building a wallet.

Modern wallets don’t just generate one key pair. They follow a design called a hierarchical deterministic (HD) wallet, defined by a standard called BIP32. An HD wallet starts from a single master seed and mathematically derives an entire tree of private and public keys from it. This means you can generate a fresh address for every transaction while only needing to back up one seed. The derivation follows a path structure that looks like this: m / purpose' / coin_type' / account' / change / address.

That seed itself is created using BIP39, which converts random entropy into a human-readable recovery phrase, typically 12 or 24 words from a standardized word list. This is the phrase users write down and store safely. Your wallet code generates the mnemonic, then converts it into a binary master seed (optionally protected by an additional passphrase), and from there BIP32 takes over to derive all the keys.

BIP44 builds on top of BIP32 by defining a specific path structure that supports multiple cryptocurrencies and multiple accounts within a single wallet. If you want your wallet to handle both Bitcoin and Ethereum from the same recovery phrase, BIP44 is the standard that organizes the key tree so each coin type and account has its own branch. The path m / 44' / 60' / 0' / 0 / 0, for example, points to the first Ethereum address in the first account.

Choosing a Development Language and Library

You don’t need to implement elliptic curve cryptography from scratch. Well-tested open-source libraries handle key generation, address derivation, and transaction signing. Your choice of library depends on which blockchain you’re targeting and which programming language you prefer.

For Ethereum and EVM-compatible chains, two JavaScript/TypeScript libraries dominate. Ethers.js is lightweight and modular, designed to be straightforward for developers who want clean abstractions over wallet creation, contract interaction, and transaction signing. Web3.js is a larger, more established collection of libraries that serves as a bridge between your application and an Ethereum node, supporting HTTP, IPC, and WebSocket connections. If you’re working in Python, Web3.py provides similar Ethereum interaction capabilities with a Pythonic API.

For Bitcoin, BitcoinJS is the go-to JavaScript library. It handles key pair generation, address creation (including SegWit formats), and transaction construction. Other ecosystems have their own libraries: Solana has @solana/web3.js, and most major blockchains maintain official or community-supported SDKs.

A typical starting point for an Ethereum wallet in JavaScript looks something like this: install Ethers.js, use its Wallet.createRandom() method to generate a new wallet with a mnemonic phrase, and you immediately have access to the private key, public key, and address. From there, you connect the wallet to a provider (a blockchain node) to check balances and send transactions.

Connecting to a Blockchain Network

A wallet is useless without a connection to the blockchain it operates on. Your wallet needs to read data (checking balances, fetching transaction history) and write data (broadcasting signed transactions). This requires access to a blockchain node.

Running your own node gives you full independence but requires significant storage, bandwidth, and ongoing maintenance. Most wallet developers instead connect to a blockchain infrastructure provider, a service that runs and maintains nodes on your behalf and exposes API endpoints you can call. You send standard JSON-RPC requests to their servers, and they relay the data to and from the blockchain.

The major providers include QuickNode (supporting over 65 blockchains), Alchemy (known for enhanced APIs covering NFTs, tokens, and transfers along with debugging tools), and Infura (tightly integrated with the Ethereum ecosystem and MetaMask). For Solana-specific development, Helius offers RPC endpoints and APIs tailored to Solana’s architecture. Chainstack, Ankr, and GetBlock round out the field with multi-chain support and both shared and dedicated node options.

Most of these services offer free tiers with rate limits that work fine during development and testing. You’ll typically sign up, get an API key, and point your library’s provider configuration at their endpoint URL. In Ethers.js, for example, you’d create a JsonRpcProvider with your Alchemy or Infura URL, then attach your wallet instance to that provider.

Building Core Wallet Features

Once you have key generation and blockchain connectivity working, you need to build the features users expect from a functional wallet.

Balance checking queries the blockchain for the amount of cryptocurrency held at your wallet’s address. For Ethereum, this is a single RPC call. For tokens (like ERC-20 tokens on Ethereum), you need to query each token’s smart contract to get the balance, which is why enhanced APIs from providers like Alchemy are helpful since they can return all token balances in one call.

Transaction signing and sending is the core action. Your wallet constructs a transaction object (specifying the recipient, amount, gas fees, and a nonce that prevents replay attacks), signs it with the private key, and broadcasts it to the network through your provider. The library handles the cryptographic signing, but your code needs to estimate gas costs, set appropriate fees, and handle errors like insufficient funds or network congestion.

Transaction history requires either indexing blockchain data yourself or relying on your infrastructure provider’s enhanced APIs. Raw blockchain nodes don’t offer a simple “get all transactions for this address” endpoint, so most wallets use provider APIs or third-party indexing services for this.

Recovery phrase backup and import lets users back up their wallet by writing down the BIP39 mnemonic and restore it later by entering those words. Your wallet code takes the mnemonic, regenerates the master seed, and re-derives all the keys using the same BIP32/BIP44 paths.

Securing Private Keys

How you store private keys determines whether your wallet is safe to use. A private key stored in plain text on disk is one malware infection away from total loss. The approach differs depending on the platform you’re building for.

For a desktop or web wallet, encrypt private keys before storing them locally. A common approach is to derive an encryption key from a user-chosen password using a key derivation function like PBKDF2 or scrypt, then encrypt the private key with AES-256. The encrypted keystore file can be saved to disk. Ethereum’s official keystore format (used by tools like Geth) follows this pattern, and Ethers.js can generate and read these files directly.

For mobile wallets, use the platform’s secure enclave or keychain. iOS provides the Secure Enclave and Keychain Services. Android offers the Keystore system. These hardware-backed storage mechanisms keep keys isolated from the rest of the operating system, making extraction significantly harder even on a compromised device.

Never store private keys on a server. If your wallet architecture requires any server-side component, design it so the server never sees or handles private keys. All signing should happen on the user’s device. This is the fundamental distinction between a non-custodial wallet (where the user holds their own keys) and a custodial wallet (where a third party holds them).

Custodial vs. Non-Custodial: Regulatory Implications

If you’re building a wallet where you control users’ private keys on their behalf, you’re building a custodial wallet, and the regulatory requirements change dramatically. Operating a custodial wallet typically requires licensing, implementing KYC (know your customer) and AML (anti-money laundering) programs, monitoring transactions, filing regulatory reports, and potentially carrying insurance. These obligations mirror what traditional financial services companies face.

Non-custodial wallets, where the user generates and stores their own keys and your software simply facilitates the process, are generally subject to far less regulation. The user is responsible for their own funds, and your application is a tool rather than a financial intermediary.

For most independent developers, building a non-custodial wallet is the practical choice. It avoids the legal complexity, licensing costs, and liability that come with holding other people’s money.

Testing Before You Ship

Every major blockchain has a testnet, a parallel network that functions identically to the main network but uses worthless tokens. Ethereum has the Sepolia and Holesky testnets. Bitcoin has its own testnet and signet. You can get free testnet tokens from faucets (websites that distribute them) and use them to test every function of your wallet without risking real money.

Test key generation by creating wallets, backing them up with the recovery phrase, and restoring them to confirm you get the same addresses. Test transaction signing by sending testnet tokens between addresses. Test edge cases: what happens when a user enters an invalid address, when the network is congested, or when a transaction fails. Run your encrypted key storage through scenarios where the user enters the wrong password.

If you’re building for others, consider having the cryptographic components audited by a security firm. A bug in key derivation or signing logic could mean permanent loss of funds for your users, and unlike traditional software, there’s no way to reverse a blockchain transaction.