SOL is the 'native token' of Solana, but we can also create our own tokens. The Token Program is one of the most important native programs in Solana. It enables the creation and management of fungible and non-fungible tokens.
One advantage of Solana's account/program model is that we don't need a separate program for each token type (like ERC20 vs ERC721 in Ethereum). Instead, we can use the same program for both fungible and non-fungible tokens. All we need is to send a set of instructions to the Token Program.
Key Concepts
-
Mint Account: The source account that defines a token
- Contains metadata like supply, decimals, mint authority
- Created using
spl-token create-token
- Each token type has one mint account, like this USDC
-
Token Account: Holds token balances for a specific mint
- Each wallet needs a token account per token type
- Created using
spl-token create-account
- Contains owner, mint, and balance information
-
Associated Token Account (ATA):
- Deterministic token account address that connects a specific wallet to a token
- Created using
getAssociatedTokenAddress
- PDA([wallet, TOKEN_PROGRAM_ID, mint])
Working with SPL Tokens
The best way to understand SPL tokens is to walk through creating and managing an SPL token using the Solana CLI (installation guide):
- Create two new Solana wallets
solana-keygen new --force ~/my_solana_wallet1.json
solana-keygen new --force ~/my_solana_wallet2.json
- Create a new token with the specified mint authority (mint token)
spl-token create-token --mint-authority ~/my_solana_wallet1.json
- Store the token address in a variable in your terminal
TOKEN1=7gqyYWS8fpjvtbjWx2Qk1GPQpGHEasf7moBsns1gJkpf # Replace with actual token address from the previous step
- Check the mint token information
solana account $TOKEN1
It should return the token metadata like address, supply, decimals, and mint authority. You can check the same info on Solana Explorer.
- Store wallet addresses in variables in your terminal (these needs to be created before)
SOLADDR1=$(solana address -k ~/my_solana_wallet1.json)
SOLADDR2=$(solana address -k ~/my_solana_wallet2.json)
- Set the configuration to use wallet1
solana config set --keypair ~/my_solana_wallet1.json
- Airdrop SOL to wallet1 and wallet2
solana airdrop 100 $SOLADDR1
solana airdrop 200 $SOLADDR2
- Create an associated token account for wallet1 (token account) and store the address in a variable
TOKENACCT1=$(spl-token create-account $TOKEN1 --owner $SOLADDR1 --fee-payer ~/my_solana_wallet1.json | grep 'Creating account' | awk '{print $3}')
- Mint 100 tokens to the token account (minting and transferring tokens)
spl-token mint $TOKEN1 100 --recipient $TOKENACCT1
- Verify the token balance
spl-token supply $TOKEN1
spl-token balance $TOKENACCT1
- Create an associated token account for wallet2 (token account) and store the address in a variable
TOKENACCT2=$(spl-token create-account $TOKEN1 --owner $SOLADDR2 --fee-payer ~/my_solana_wallet2.json | grep 'Creating account' | awk '{print $3}')
- Transfer 25 tokens from wallet1 to wallet2 (transferring tokens)
spl-token transfer $TOKEN1 25 $TOKENACCT2 --owner ~/my_solana_wallet1.json --fee-payer ~/my_solana_wallet1.json
- Check the balances of both accounts (checking balances)
spl-token balance $TOKENACCT1
spl-token balance $TOKENACCT2
- Verify the token accounts (checking wallet associated token accounts)
spl-token accounts --owner $SOLADDR1
spl-token accounts --owner $SOLADDR2
NFTs
NFTs (non-fungible tokens) are actually just SPL tokens with a few key constraints:
- They use
--decimals 0
when creating the token, since there should be only one token - Only one token is minted, and then minting is disabled to ensure uniqueness
While you can create NFTs manually using the SPL token program this way, in practice most developers use tools like Candy Machine to handle the image/metadata upload and minting process.