Making a Bitcoin wallet is incredibly easy.
In fact, it is probably the easiest wallet to make in the world.
It would be a challenge to make a wallet for the traditional banking system in under a year, but making a Bitcoin wallet takes just 20 minutes.
Today I’m going to teach you how.
Before building a wallet, it’s important to know the basics of wallet theory and the bitcoin transaction model.
If this is too basic for you, feel free to skip the next two sections and get right to the code.
Wallet Theory
What is a wallet exactly?
At its core, a wallet (bitcoin or otherwise) provides three main functions:
The ability to view your balance
The ability to receive money
The ability to send money
Depositing is the same as receiving money. Withdrawing is the same as sending money. They are just special cases where you are the sender of the receive action and where you are the receiver of the send action.
Some wallets may complicate this a bit but they are extensions of the core.
In Bitcoin country, wallets really are as simple as this.
Building a wallet will require us to remember these three functions and design around them.
The Bitcoin Transaction Model
The next topic for us to understand is the bitcoin transaction model.
Understanding this will give us the foundation for implementing the three core features of our wallet: view balance, receive and send.
The way that balances are secured on bitcoin is very simple.
Don’t worry if you don’t get it right away, it can be a bit confusing, but rest assured it is simple and it will become second nature to you as time goes on.
In Bitcoin, money resides in virtual locations.
These locations are identified by numbers known as “addresses.”
And they are unlocked by other numbers that act as virtual keys.
These virtual numerical keys are known as “private keys” because you are must keep them private or otherwise anyone can take your money.
Every address has a corresponding private key. They are generated at the same time and have an important mathematical relationship, which we’ll discuss later.
You send money out of your address by using your private key while at the same time making sure not to reveal your key to anyone else.
You do this by performing an action that only your address’s corresponding key could possibly perform: you use the key to create a digital signature around the description of the transaction.
Then you broadcast the transaction to the bitcoin network.
The bitcoin network (A.K.A. the collection of computers running the bitcoin software) checks the transaction to make sure: (a) it is trying to spend funds that are available and (b) it has a signature that corresponds to the hypothetical key that is tied to the address where the funds reside.
How does the network know that the signature corresponds to the address?
This is perhaps the most complicated part to understand, but we will try to get through it as simply as possible.
When a Bitcoin address is created, it is created alongside its corresponding private key. The two numbers are linked mathematically.
One number, the bitcoin address, can be easily derived from the other number, but the reverse computation is not feasible.
This is called a one-way function, because you can only go from “A” to “B” but not from “B” to “A”.
A good analogy would be that it is easy to check that two types of ground meat are the same, and it is easy to grind beef or turkey into ground meat, but it is essentially impossible to turn ground meat into its unground counterpart.
Going from a private key to an address is grinding meat - doable. Generating a signature from a private key is grinding meat - doable. Checking a signature against an address is comparing two types of ground meat - doable. Going from an address to a private key is un-grinding meat - impossible.
So there we have it.
The way to know that a transaction was signed by the correct hypothetical private key - the one that corresponds to the address where the money resides - is to check the signature against the address.
You don’t need to actually know the private key to know that the signature is correct. You just need to verify the signature mathematically against the address.
Creating Keys and Addresses
Now we’re ready to build the foundation of our wallet.
This is the code for wallet generation, or the creation of the private keys that allow you to spend your funds and the addresses that allow you to check your balance and receive funds.
As we mentioned before, the address and the private key are mathematically linked.
The process for creating a Bitcoin address looks like this:
Create a large random number that is mathematically infeasible to guess - this is the private key.
Use elliptic curve cryptography to calculate a public equivalent of this number - this is the public key (a really large number can be easily raised to a certain exponential power but the resulting number cannot be easily raised to the inverse power).
Take the public key and calculate a cryptographic hash of the public key - this is the public key hash.
Build an “unencoded Bitcoin address” by using the Bitcoin scripting language to specify a location where funds can be spent under the following condition, expressed in natural language: “funds can be spent from this address when a valid transaction is revealed with a signature produced from a private key that corresponds to a public key that when hashed equals a particular public key hash”.
Take the unencoded bitcoin address and encode it into base58 to produce the final Bitcoin address.
Ok so we have our basic steps. Let’s put them into action.
We’re going to be using JavaScript to make this wallet so that it can run in the browser, it can run on the desktop (via desktop app wrappers like Electron), and it can run on mobile (via mobile app wrappers).
In my experience, the best Bitcoin library for JavaScript is BitcoinJS Lib.
First, we go into the command line and install the library (as well as a few of supporting libraries):
npm install bitcoinjs-lib
npm install ecpair bip32 tiny-secp256k1
Next, we import the necessary libraries into our codebase:
import ECPairFactory from 'ecpair'
import * as ecc from 'tiny-secp256k1'
import * as bitcoin from bitcoinjs-lib
After that, we create a key pair:
const ECPair = ECPairFactory(ecc)
const keyPair = ECPair.makeRandom()
const { address } = bitcoin.payments.p2pkh({ pubkey: keyPair.publicKey })
When it comes to *creating* a Bitcoin wallet, this is all the core code that we need!
We can now take this code and incorporate it into a page where users can generate their own Bitcoin wallets and view their respective private keys and bitcoin addresses.
Implementing “View Balance”
Now that we have implemented wallet creation, we can move on to implementing the first of our core wallet features: the“view balance” feature.
We do this simply by issuing an HTTP request to a Bitcoin blockchain API. This is a website that runs a special version of bitcoin node software that keeps track of the balances for all addresses. This in turn means that you can ask it for the balance of any address and it’ll give you the answer.
There are many options out there but the first I would check out is Blockcypher.
Go to the documentation for their balance endpoint and you’ll see that you can lookup addresses with the following path:
/addrs/$ADDRESS/balance
Let’s use the following address as our example address:
const address = "1DEP8i3QJCsomS4BSMY2RpU1upv62aGvhD"
Now we can insert the example address in the path and create a URL that we can use to get information from the API
const url = `https://api.blockcypher.com/v1/btc/main/addrs/${address}/balance`
Now that we have our URL, we can make a call to the API and log the results to the console as follows:
const addressData = await fetch(url).json()
console.log(addressData)
Once you do this, you should see data in your console that looks something like this:
{
"address": "1DEP8i3QJCsomS4BSMY2RpU1upv62aGvhD",
"total_received": 4654010,
"total_sent": 0,
"balance": 4654010,
"unconfirmed_balance": 0,
"final_balance": 4654010,
"n_tx": 16,
"unconfirmed_n_tx": 0,
"final_n_tx": 16
}
Bitcoin uses 8 decimal places for its balances, so to get the balance in Bitcoins for this address, we simply take the “final_balance” figure which is “4654010” and we divide it by 10^8. That gives us:
0.0465401
The address holds approximately 0.0465 Bitcoins.
With a frontend framework like React, we can display the user’s balance in big characters.
<h1>{addressData.final_balance / 10**8}</h1>
Part II
So there you have it. You’ve learned about how Bitcoin wallets work under the hood, you’ve learned how to create a Bitcoin wallet’s address and private key, and you’ve learned how you can display the balance of the Bitcoin wallet to the user.
In part two of this tutorial, we’ll show you how to implement the “Receive” and “Send” functionality of a wallet.
how do i get the part2 for the project
Thanks, Ryan. Nice simplification. Can we expand language .. to wallets holding “keys to ALL my assets” (somehow getting across that wallets hold keys, NOT balances or assets). And wallet is NOT actually receiving or sending to/from wallet … but rather unlocking multiple, various chain balances (with the keys within).