6 min read
Overview
Whether you are querying a token account balance or constructing a token transfer instruction, knowing how to derive a user's token account address is a fundamental skill for any Solana developer. In this guide, we will walk through five easy ways to fetch the address of a Solana SPL-associated token account:
- Using Solana's SPL-Token Command Line Interface (SPL-Token CLI) (Jump to SPL-Token CLI)
- Using Solana's JavaScript API (Jump to Solana-Web3.js)
- Using Solana's SPL Token Program API (Jump to SPL Token Program)
- Using a cURL script (Jump to cURL)
- Using Rust (Jump to Rust)
What You Will Need
- Basic understanding of Solana Fundamentals
- Solana CLI latest version installed
- SPL Token Program CLI latest version installed
- Nodejs (version 16.15 or higher) installed
- Basic JavaScript experience
- cURL stable version installed
- A wallet address and mint address to query (we will use the wallet:
E645TckHQnDcavVv92Etc6xSWQaq8zzPtPRGBheviRAk
and USDC token mint,EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
) - Rust installed (optional for Rust method)
Dependency | Version |
---|---|
solana-cli | 1.16.14 |
spl-token-cli | 3.1.1 |
node.js | 16.15 |
curl | 8.1.12 |
@solana/web3.js | 1.78.5 |
@solana/spl-token | 0.3.7 |
solana-sdk | 1.16.14 |
spl-associated-token-account | 2.2.0 |
cargo | 1.69.0 |
SPL Token Accounts
Before diving into the code, let's take a moment to recap what a token account is and how it differs from a Solana wallet address. Just like most elements of the Solana ecosystem, token accounts are built on Solana's account model. This means that token accounts are actually Solana accounts that are associated with a specific token mint. These accounts are owned by the SPL Token Program (TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA
) and controlled by a user's wallet address. Though having multiple token accounts associated with a single wallet address is possible, each token account is unique to a specific mint. To reduce friction in token management, Solana introduced the Associated Token Program, a way to deterministically map a user's wallet to a token account for an associated mint. This guide will focus on how to fetch the address of an associated token account for a given wallet and mint.
Method 1 - SPL-Token CLI
Our first method is to check the balance of a wallet using Solana SPL-Token CLI. If you do not already have it installed, follow the instructions for your operating environment at spl.solana.com/token. To make sure your installation was successful, open a new terminal and type:
spl-token --version
You should see something like this:
You're ready to go! All you need to do is get your wallet address handy--you can copy it directly from Phantom or any other wallet:
You will also need the mint address of the token you want to query. You can find this by searching for the name of the token on any Solana-based explorer, e.g., Solana Explorer:
In your terminal, fetch your token account by entering:
spl-token address --owner OWNER_WALLET_ADDRESS --token TOKEN_MINT_ADDRESS --verbose -um
We simply pass the --owner
flag with the wallet address we want to query, the --token
flag with the mint address of the token we want to query, and the --verbose
flag to get a more detailed response (required for this query). The -um
flag tells the CLI to use the Solana mainnet cluster (though our search is deterministic and should not require a specified cluster, the CLI tool verifies that our mint address is actually a valid mint address on that cluster).
You should see something like this:
Great job!
Method 2 - Solana-Web3.js
Create a new project directory and file, balance.js, in your terminal with the following:
mkdir token-address && cd token-address && echo > address.js
Install Solana Web3 dependencies:
yarn init -y
yarn add @solana/web3.js
or
npm init -y
npm install --save @solana/web3.js
Open address.js in a code editor of choice, and on line 1, require @solana/web3.js. We will deconstruct the PublicKey class from this package.
const { PublicKey } = require('@solana/web3.js');
On lines 3-6, define your wallet, mint, and the relevant programs (Token Program and Associated Token Program):
const OWNER = new PublicKey('YOUR_WALLET_ADDRESS'); // e.g., E645TckHQnDcavVv92Etc6xSWQaq8zzPtPRGBheviRAk
const MINT = new PublicKey('YOUR_MINT_ADDRESS'); // e.g., EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
const TOKEN_PROGRAM_ID = new PublicKey('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA');
const ASSOCIATED_TOKEN_PROGRAM_ID = new PublicKey('ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL');
Finally, fetch your address by calling the findProgramAddressSync()
method on PublicKey:
const [address] = PublicKey.findProgramAddressSync(
[OWNER.toBuffer(), TOKEN_PROGRAM_ID.toBuffer(), MINT.toBuffer()],
ASSOCIATED_TOKEN_PROGRAM_ID
);
console.log('Using Solana-Web3.js: ', address.toBase58());
The findProgramAddressSync
method deterministically finds a program address given seeds and a program ID. In this case, we pass the wallet address, token program ID, and mint address as seeds and the associated token program ID as the program ID (these seeds and their order are defined by the associated token program).
Run your code. In your terminal type,
node address
You should see something like this:
Nice job!
Note: you can alternatively use the Connection class to send a getAssociatedTokenAddressSync
request to the Solana cluster. This method requires a network request, so it is not as performant as the findProgramAddressSync
method; however, it will also find any token accounts created outside of the associated token program. Situationally, this could be useful.
Method 3 - Solana Token Program
Our last instruction was a little messy. The Solana SPL Token API makes this process a little easier. Let's look at how we can fetch the address of an associated token account using the SPL Token API.
Continuing in the same project directory as the previous method, install the SPL Token Program:
yarn add @solana/spl-token
or
npm install --save @solana/spl-token
Open address.js, and on line 1 (before our previous import), require @solana/spl-token. We will deconstruct the getAssociatedTokenAddressSync
method from this package.
const { getAssociatedTokenAddressSync } = require('@solana/spl-token');
Now, at the bottom of your script, invoke the getAssociatedTokenAddressSync
method by passing the wallet and mint address as arguments:
const address2 = getAssociatedTokenAddressSync(MINT, OWNER);
console.log('Using SPL-Token: ', address2.toBase58());
Cleaner, right? That's because, under the hood, the SPL Token API uses the same findProgramAddressSync
method we used in the previous example. You can ctrl/cmd + click the getAssociatedTokenAddressSync
method to see the source code.
Run your code. In your terminal type,
node address
You should see both methods return the same address:
Nice job!
Method 4 - cURL
cURL is a command line tool and library for transferring data with URLs. Most *nix-based systems have cURL support out of the box. Check if you have it by running the following:
curl -h
If you don't have it installed, head to curl.se to set it up.
Once you are ready to go, all you need to do is drop this HTTP request in your terminal (make sure to replace your endpoint, wallet address, and mint address). In your terminal, enter:
curl https://api.mainnet-beta.solana.com -X POST -H "Content-Type: application/json" -d '
{
"jsonrpc": "2.0",
"id": 1,
"method": "getTokenAccountsByOwner",
"params": [
"YOUR_WALLET_ADDRESS",
{
"mint": "YOUR_MINT_ADDRESS"
},
{
"encoding": "jsonParsed"
}
]
}
'
You should see something like this:
Note: You may utilize a package like jq to return formatted JSON data if you prefer.
Notice the same address is returned in the result.value[0].pubkey
field 🙌. Check out our docs for more information on the getTokenAccountsByOwner
method.
Method 5 - Rust
If you are a Rust developer, you can also use the Solana Rust SDK. Inside of your project folder, initiate a new project with the following command:
cargo new token-address
Navigate to the newly created directory:
cd token-address
Add the necessary dependencies to your Cargo.toml file:
[dependencies]
solana-sdk = "1.16.14"
spl-associated-token-account = "2.2.0"
Open src/main.rs, and on line 1, import the necessary packages:
use solana_sdk::pubkey::Pubkey;
use spl_associated_token_account::get_associated_token_address;
use std::str::FromStr;
On lines 5-6, define your owner and mint addresses:
const OWNER: &str = "YOUR_WALLET_ADDRESS";
const MINT: &str = "YOUR_MINT_ADDRESS";
Finally, modify your main
function that will fetch your address by passing the public keys of your owner and mint into the get_associated_token_address
method:
fn main() {
let owner_pubkey = Pubkey::from_str(OWNER).unwrap();
let mint_pubkey = Pubkey::from_str(MINT).unwrap();
let associated_token_address = get_associated_token_address(&owner_pubkey, &mint_pubkey);
println!("Associated Token Address: {}", associated_token_address);
}
Compile and run your code. In your terminal type,
cargo build
cargo run
And you should see your same token address returned:
Nice job!
Wrap Up
Nice work! You now have five handy tools for fetching the address of a Solana Associated Token Account. If you are just getting started with your Solana journey, here are some resources that may be helpful:
We would love to hear more about what you are building. Drop us a line in Discord, or give us a follow on Twitter to stay up to date on all the latest information!
We ❤️ Feedback!
Let us know if you have any feedback or requests for new topics. We'd love to hear from you.