Skip to main content

Five Ways to Find the Associated Token Address for a Solana Wallet and Mint

Created on
Updated on
Nov 1, 2024

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:

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)
DependencyVersion
solana-cli1.16.14
spl-token-cli3.1.1
node.js16.15
curl8.1.12
@solana/web3.js1.78.5
@solana/spl-token0.3.7
solana-sdk1.16.14
spl-associated-token-account2.2.0
cargo1.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.

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:

'Solana CLI Version Check'

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:

'Phantom Wallet Copy Button'

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:

'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:

'Solana CLI Results'

Great job!

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:

'Solana-Web3.js Results'

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.

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:

'Solana Token Program Results'

Nice job!

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:

'Solana cURL Results' 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.

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:

'Solana Rust Results'

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.

Share this guide