Files
gh-tenequm-claude-plugins-s…/skills/solana-development/references/tokens-overview.md
2025-11-30 09:01:25 +08:00

302 lines
8.2 KiB
Markdown

# SPL Token Program - Overview and Fundamentals
Overview of SPL Token Program fundamentals including program types, account structures (Mint and Token accounts), and Associated Token Accounts (ATAs) with derivation and creation patterns.
**For additional token topics, see:**
- **[tokens-operations.md](tokens-operations.md)** - Create, mint, transfer, burn, close operations
- **[tokens-validation.md](tokens-validation.md)** - Account validation patterns
- **[tokens-2022.md](tokens-2022.md)** - Token Extensions Program features
- **[tokens-patterns.md](tokens-patterns.md)** - Common patterns and security
## Table of Contents
1. [Token Program Overview](#token-program-overview)
2. [Token Account Structures](#token-account-structures)
3. [Associated Token Accounts](#associated-token-accounts)
---
## Token Program Overview
### SPL Token vs Token-2022
**SPL Token (Original):**
- Program ID: `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA`
- Production-ready, stable, widely adopted
- No new features planned
- Use for standard fungible tokens
**Token-2022 (Token Extensions Program):**
- Program ID: `TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb`
- Backwards-compatible with SPL Token
- Supports extensions (transfer fees, confidential transfers, metadata pointers, etc.)
- Use for advanced token features
### Key Concepts
```
┌─────────────────────────────────────────┐
│ Mint Account │
├─────────────────────────────────────────┤
│ - Defines a token type │
│ - Controls supply │
│ - Has mint authority (can create tokens)│
│ - Has freeze authority (can freeze accts)│
└─────────────────────────────────────────┘
│ Creates
┌─────────────────────────────────────────┐
│ Token Account │
├─────────────────────────────────────────┤
│ - Holds token balance │
│ - Owned by a wallet or program │
│ - Associated with specific Mint │
│ - Can be frozen/delegated │
└─────────────────────────────────────────┘
```
### Required Dependencies
**For Anchor:**
```toml
[dependencies]
anchor-lang = "0.32.1"
anchor-spl = "0.32.1"
[features]
idl-build = [
"anchor-lang/idl-build",
"anchor-spl/idl-build",
]
```
**For Native Rust:**
```toml
[dependencies]
spl-token = "6.0"
spl-associated-token-account = "6.0"
solana-program = "2.1"
```
---
## Token Account Structures
### Mint Account
**Size:** 82 bytes
```rust
pub struct Mint {
/// Optional authority to mint new tokens (Pubkey or None)
pub mint_authority: COption<Pubkey>, // 36 bytes
/// Total supply of tokens
pub supply: u64, // 8 bytes
/// Number of decimals (0 for NFTs, typically 6-9 for fungible)
pub decimals: u8, // 1 byte
/// Is initialized?
pub is_initialized: bool, // 1 byte
/// Optional authority to freeze token accounts
pub freeze_authority: COption<Pubkey>, // 36 bytes
}
```
**COption Format:**
```rust
pub enum COption<T> {
None, // Represented as [0, 0, 0, 0, ...]
Some(T), // Represented as [1, followed by T bytes]
}
```
### Token Account
**Size:** 165 bytes
```rust
pub struct Account {
/// The mint associated with this account
pub mint: Pubkey, // 32 bytes
/// The owner of this account
pub owner: Pubkey, // 32 bytes
/// The amount of tokens this account holds
pub amount: u64, // 8 bytes
/// If `delegate` is `Some` then `delegated_amount` represents
/// the amount authorized by the delegate
pub delegate: COption<Pubkey>, // 36 bytes
/// The account's state
pub state: AccountState, // 1 byte
/// If is_native.is_some, this is a native token, and the value logs the
/// rent-exempt reserve
pub is_native: COption<u64>, // 12 bytes
/// The amount delegated
pub delegated_amount: u64, // 8 bytes
/// Optional authority to close the account
pub close_authority: COption<Pubkey>, // 36 bytes
}
pub enum AccountState {
Uninitialized,
Initialized,
Frozen,
}
```
---
## Associated Token Accounts
### What are ATAs?
**Associated Token Accounts (ATAs)** are PDAs that map a wallet address to a token account for a specific mint.
**Derivation:**
```rust
ATA = PDA(
seeds: [wallet_address, TOKEN_PROGRAM_ID, mint_address],
program: ASSOCIATED_TOKEN_PROGRAM_ID
)
```
**Benefits:**
- **Deterministic**: Same wallet + mint always produces same ATA
- **Discoverable**: Easy to find a user's token accounts
- **Standard**: All wallets use this convention
**Constants:**
```rust
// Token Program ID
pub const TOKEN_PROGRAM_ID: Pubkey = pubkey!("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA");
// Associated Token Program ID
pub const ASSOCIATED_TOKEN_PROGRAM_ID: Pubkey = pubkey!("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL");
```
### Finding ATA Address
#### Using Anchor
```rust
use anchor_spl::associated_token::get_associated_token_address;
// In client code or tests
let ata_address = get_associated_token_address(
&wallet_address,
&mint_address,
);
```
#### Using Native Rust
```rust
use spl_associated_token_account::get_associated_token_address;
// Derive ATA address
let ata_address = get_associated_token_address(
&wallet_address,
&mint_address,
);
```
### Creating Associated Token Accounts
#### Using Anchor
```rust
use anchor_spl::associated_token::AssociatedToken;
use anchor_spl::token_interface::{Mint, TokenAccount, TokenInterface};
#[derive(Accounts)]
pub struct CreateTokenAccount<'info> {
#[account(
init,
payer = payer,
associated_token::mint = mint,
associated_token::authority = owner,
associated_token::token_program = token_program,
)]
pub token_account: InterfaceAccount<'info, TokenAccount>,
pub mint: InterfaceAccount<'info, Mint>,
/// CHECK: Can be any account
pub owner: UncheckedAccount<'info>,
#[account(mut)]
pub payer: Signer<'info>,
pub token_program: Interface<'info, TokenInterface>,
pub associated_token_program: Program<'info, AssociatedToken>,
pub system_program: Program<'info, System>,
}
pub fn create_ata(ctx: Context<CreateTokenAccount>) -> Result<()> {
// ATA is automatically created by Anchor constraints
Ok(())
}
```
#### Using Native Rust
```rust
use spl_associated_token_account::instruction::create_associated_token_account;
use solana_program::{
account_info::AccountInfo,
entrypoint::ProgramResult,
program::invoke,
};
pub fn create_ata(
payer: &AccountInfo,
wallet: &AccountInfo,
mint: &AccountInfo,
ata: &AccountInfo,
system_program: &AccountInfo,
token_program: &AccountInfo,
associated_token_program: &AccountInfo,
) -> ProgramResult {
invoke(
&create_associated_token_account(
payer.key,
wallet.key,
mint.key,
token_program.key,
),
&[
payer.clone(),
ata.clone(),
wallet.clone(),
mint.clone(),
system_program.clone(),
token_program.clone(),
associated_token_program.clone(),
],
)?
;
Ok(())
}
```
---
## Next Steps
- **Token Operations**: See [tokens-operations.md](tokens-operations.md) for creating mints, minting, transferring, burning, and closing accounts
- **Validation**: See [tokens-validation.md](tokens-validation.md) for account validation patterns
- **Token-2022**: See [tokens-2022.md](tokens-2022.md) for Token Extensions Program features
- **Patterns & Security**: See [tokens-patterns.md](tokens-patterns.md) for common patterns and security best practices