Crypto wallets are the most critical piece of user-facing infrastructure in the blockchain space. In the same way that the browser brought the web to a mass audience by providing an easy-to-use gateway into the underlying servers and databases, wallets provide users with an easy-to-use gateway into blockchain protocols.
A wallet is less like the wallet you use for your credit cards, and a lot more like a keychain. If you think of a blockchain as a giant bank safe with digital safety deposit boxes, wallets are the keychains where you keep the key to your box. Once you have access to a box, you can manage the contents of it by receiving, sending, holding and spending digital assets.
Figure 3: Wallets hold private keys to your public address on a blockchain
We can think of the box itself as a chunk of memory on the blockchain. The digital box location is referred to as a public key, or more intuitively as a public address, and can be shared with anyone in the same way you might share your address to receive mail at home. As the name implies, this is widely available to others on the network and it is the identifier others use to send digital assets to a box.
The key that can unlock the safety deposit box is referred to as the private key. Anyone with access to a box's private key has access to the box, which is why it's paramount to keep the key private - hence the name, private key.
Run and open the app in your browser at http://localhost:3000. You'll notice the frontend offers the user the option to create a new wallet or import an existing wallet.
Clicking on Create New Wallet routes the user to a
/generatepage signaling to our user that by clicking Generate, the app will generate a key phrase and thus create a new wallet. But when we click Generate, we're routed to a
/phrasepage with an empty phrase container.
For the app to work, we need to implement a function that generates a phrase and uses it to create a wallet when the
/phrasepage renders. In your editor, navigate to
In order to generate the phrase, we need to leverage an external library that satisfies the BIP39 specification, which set the standard for generating phrases for deterministic keys.
Fortunately, there's the Bip39 library. It provides us with the functionality we need to generate the phrase and later convert it into the seed we need to generate our Solana wallet keys.
We already installed the library when we ran
yarnduring set up because we included it into the pre-built app's package.json. So all we need to do is import it:
Recall that secret recovery phrases are also called mnemonics and Bip39 includes the method
generateMnemonic()for generating mnemonic phrases. We can call it and replace the variable currently assigned to an empty string:
This allows us to set the phrase in state and display it for our user to write down and store safely. With this step we have effectively created our wallet because the phrase by itself will allow its holder to access the account that matches it.
Before we can connect to the account on the blockchain, however, we need to convert the phrase into a form that the blockchain can understand. After all, mnemonic phrases are abstractions that translate a long, archaic number into a more human-friendly form.
We need to convert the phrase into bytes so the Solana web3.js library can use it to generate a
keypairwill be the wallet account consisting of a public key that can encrypt data and a private key that can decrypt data.
By reviewing Solana's web3.js documentation, we see that there's a
Keypairclass defined as "an account keypair used for signing transactions." This is exactly what we need to generate using the mnemonic phrase.
We notice that the
Keypairclass has a
fromSeedmethod that generates a keypair from a 32-byte seed. It also mentions that the seed needs to be a
Uint8Array, which means we'll need a way to convert our
stringphrase into a
Going back to the Bip39 library we see a method called
mnemonicToSeedSync(mnemonic)that returns some sort of
Bufferobject that looks like a list of hexadecimal numbers. We can test this by running it in our application and passing in the mnemonic we generated:
It looks like we're close. The
Keypairclass requires a 32-byte
Uint8Arrayand we're getting a 64-byte
Uint8Array. We can slice the seed and keep only the first 32 bytes:
With the seed in the right format, we can use
fromSeedmethod to generate an account keypair:
We then set the account into context state and we have access to a Solana wallet.
Once you implement the functionality, make sure you save the recovery phrase before you click Finish on the browser. We'll be using it in Step 6 to access the wallet once after logging out.
Once you click on Finish, you'll be routed to the wallet page that displays the account's dashboard. You'll notice this page includes a few other features. We'll discuss the Network dropdown in Step 3 while implementing the crucial functionality of showing users their balance.
In Step 4 we'll dive into airdrops and make the Airdrop button functional, and in Step 5 we'll enable the Send button and transfer funds.
Listing 2.2: Code for creating a wallet
In your editor, navigate to
pages/phrase.tsxand follow the steps included as comments to finish writing the function. We include a description along with a link to the documentation you need to review in order to implement each line. The relevant code block is also included in Listing 2.1 below.
Listing 2.1: Instructions for generating a phrase and creating a wallet
Step 1: Getting Up and Running 🏃
Step 3: Fetch a Balance ⚖️