Crypto wallets serve one primary function - storing your private keys. By storing your private keys, they allow you to manage - transfer, receive, organize - your digital assets. Part of that functionality requires the wallet to retrieve certain data that is stored onchain to display on your user dashboard.
A balance represents a certain amount of cryptocurrency or tokens held by an account. If you think of the blockchain as a database that keeps ownership records, and of the public keys as the owner IDs, then you can think of the balances as an integer column in the database that tracks how much of a certain token each owner holds.
We'll be connecting to one of Solana's networks, and fetching the balance for the account we just created. Later in Step 4, we'll be funding the account with test tokens using the airdrop function.
The concept of various networks for a single protocol is similar to that of different environments for an app (e.g. development, test, production, etc). Typically blockchain protocols have a main network or mainnet, which refers to the production blockchain with real economic value and official transactions, and at least one experimentation network, which refers to an identical blockchain used to test features before they go live on mainnet.
Figure 4: It's always important to test on devnet before deploying on mainnet
Solana has a production network called mainnet and two experimentation networks called testnet and devnet. Solana's devnet is designed for developers and users to play with various features and debug dApps before launching on mainnet with real economic consequences. The testnet is where Solana tests potential protocol updates.
You'll notice the wallet includes a dropdown at the top-right that allows users to select what network they want to connect to. This allows the wallet to manage assets specific to the connected network. Our default network is devnet since we'll be using it to receive test tokens in Step 4 and then transfer them in Step 5, but the functionality we'll build will work for any of the Solana networks.
In Step 2, we discussed how a wallet is more like a keychain that holds keypairs representing an account address and the key to access it. We built a function that allowed us to generate a unique account and the corresponding phrase that works like a password for accessing the account. Now we need to connect with the Solana blockchain so we can fetch the account's balance, which at this point should be zero because we just created it.
The first step for interacting with any blockchain is to instantiate a connection. Conveniently there's a
Connectionclass in web3.js designed to do just that. By reviewing the documentation, we notice the
Connectionconstructor requires two arguments:
commitmentOrConfig?: Commitment | ConnectionConfig.
The description for
endpointmentions that it's a "URL to the fullnode JSON RPC endpoint". Since we don't have a URL for the connection, we need to either find one from Solana or look for a function that will return a URL. By searching the web3.js docs for "URL", we see that there's a function called
clusterApiUrlthat returns the "RPC API URL for the specified cluster". Moreover, if we review the
Clustertype, we see that it refers to the network we want to connect to.
commitmentOrConfig, it looks like the definition for
Commitmenttypes describes it as the "level of commitment desired when querying state", which is a meaningless definition to us at this point. However, it looks like
Commitmentcan be one of several strings so we should choose one and test the function. In this case, we can choose "confirmed" as a reasonable guess and move forward.
Putting the above together, we can start implementing the
refreshBalancefunction with a connection instance in
Now that we have a connection, we need to fetch our account's balance. We might speculate that there should be a
getBalancefunction that takes an account's public address as a parameter, and returns the account's balance. Searching for the keyword "balance" in the web3.js docs, we can see that, not only is there a
getBalancemethod, but it's a
Connection, we can see it expects the account's public key as a parameter.
There are a few ways to structure this part of the function. We've chosen to assign the
publicKeyvariable to the account's public key, and then pass that into
getBalanceto query the network for the balance.
From the docs, we know
getBalancereturns a promise so we use
awaitand assign its return value to the
balancevariable. By logging
balance, we can see our account has zero balance as expected.
But that's a bit anticlimactic. We know it's a new account and it should have zero balance. Nothing changed on the frontend because the default value was zero. We need to fund the account to see the balance change, and we'll do just that in Step 4.
Listing 3.2: Code for fetching a balance
If you open the browser's console from the
/walletpage, you'll notice a message that reads, "Balance functionality not implemented yet!". Navigate to
utils/index.tsin your editor and follow the steps included as comments to finish writing the
refreshBalancefunction. 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 3.1 below.
Listing 3.1: Instructions for fetching an account's balance
Step 2: Create a Wallet 💼
Step 4: Airdrop Funds 🪂