How to Interact with Tokens in Solana Programs — A Developer Guide

Learn how to mint, reward, and burn SPL tokens in Solana games using Anchor, enabling in-game currency, rewards, and consumable mechanics.

4 min read
By rottie
How to Interact with Tokens in Solana Programs — A Developer Guide

Tokens on Solana especially SPL tokens can be powerful tools in blockchain games. You can use them for in‑game rewards, currency systems, healing items, and much more. This guide breaks down the official Solana tutorial into understandable parts and highlights how tokens can be used in game logic.

What This Guide Teaches

This example teaches you how to build a game program using Anchor (a Solana framework) that:

  • Creates custom tokens
  • Assigns tokens to players
  • Rewards players when they defeat enemies
  • Burns tokens to heal players

It’s a practical way to see how tokens work inside on‑chain game logic.

Core Concepts

1. Token Program & Metadata

Solana uses the SPL Token Program for all token interactions minting, transferring, burning, etc.
The tutorial also uses Token Metadata to attach human‑readable data (like name and symbol) to a token.

Tokens on Solana are not smart contracts themselves. Instead:

  • A token mint defines the token (like a coin type)
  • Associated Token Accounts (ATAs) store token balances for wallets
    (Every token + wallet pair has its own ATA)

Building Blocks of the Tutorial

The example program has four main instructions (on‑chain actions):

1. Create Mint

This instruction lets an admin create a new token mint.

  • The mint authority is a PDA (Program Derived Address), not a regular wallet.
  • Metadata (name, symbol, URI) is created alongside the mint.
    This token will be used as the game’s currency or reward.
#[derive(Accounts)]
pub struct CreateMint<'info> {
    #[account(mut)]
    pub payer: Signer<'info>,
    #[account(
        init,
        payer = payer,
        mint::decimals = 0,
        mint::authority = mint_authority,
        mint::freeze_authority = mint_authority
    )]
    pub mint: Account<'info, Mint>,
    #[account(seeds = [b"mint_authority"], bump)]
    pub mint_authority: SystemAccount<'info>,
    pub system_program: Program<'info, System>,
    pub token_program: Program<'info, Token>,
}

2. Init Player

Each player gets a unique account tracking their health.

This sets starting health (e.g., 100) so health logic can be applied later. It does not deal with tokens yet just player data.

#[account]
pub struct Player {
    pub health: u8,
}

#[derive(Accounts)]
pub struct InitPlayer<'info> {
    #[account(init, payer = user, space = 8 + 1)]
    pub player: Account<'info, Player>,
    #[account(mut)]
    pub user: Signer<'info>,
    pub system_program: Program<'info, System>,
}

3. Kill Enemy

This is where tokens are rewarded:

  • If a player has health remaining:
    • Reduce health (e.g., −10)
    • Mint 1 token to the player’s token account
      Tokens are minted using a cross‑program invocation (CPI) to the SPL Token Program. (Solana)
#[derive(Accounts)]
pub struct KillEnemy<'info> {
    #[account(mut)]
    pub player: Account<'info, Player>,
    #[account(mut)]
    pub player_token_account: Account<'info, TokenAccount>,
    #[account(mut)]
    pub mint: Account<'info, Mint>,
    #[account(seeds = [b"mint_authority"], bump)]
    pub mint_authority: Signer<'info>,
    pub token_program: Program<'info, Token>,
}

pub fn kill_enemy(ctx: Context<KillEnemy>) -> Result<()> {
    let player = &mut ctx.accounts.player;
    if player.health > 0 {
        player.health -= 10;

        token::mint_to(
            CpiContext::new(
                ctx.accounts.token_program.to_account_info(),
                token::MintTo {
                    mint: ctx.accounts.mint.to_account_info(),
                    to: ctx.accounts.player_token_account.to_account_info(),
                    authority: ctx.accounts.mint_authority.to_account_info(),
                },
            ),
            1, // Mint 1 token
        )?;
    }
    Ok(())
}

4. Heal

This instruction lets players burn a token to restore full health.

Burning tokens gives them utility inside the game a key design in token‑based gameplay.

#[derive(Accounts)]
pub struct Heal<'info> {
    #[account(mut)]
    pub player: Account<'info, Player>,
    #[account(mut)]
    pub player_token_account: Account<'info, TokenAccount>,
    #[account(mut)]
    pub mint: Account<'info, Mint>,
    pub token_program: Program<'info, Token>,
}

pub fn heal(ctx: Context<Heal>) -> Result<()> {
    let player = &mut ctx.accounts.player;

    token::burn(
        CpiContext::new(
            ctx.accounts.token_program.to_account_info(),
            token::Burn {
                mint: ctx.accounts.mint.to_account_info(),
                from: ctx.accounts.player_token_account.to_account_info(),
                authority: ctx.accounts.player.to_account_info(),
            },
        ),
        1, // Burn 1 token
    )?;

    player.health = 100; // restore full health
    Ok(())
}

Building the Client

Once the on‑chain program is deployed, you’ll interact with it from a client app (e.g., web or mobile):

  • Use Solana’s Web3 SDKs (JavaScript, Rust, etc.) to send transactions
  • Create mint + token accounts
  • Sign transactions to call the instructions above
  • Display balances and game state
    This connects your UI to the smart contract logic.

Game Use Cases for Tokens

Using this pattern, you can apply tokens in many ways:

  • In‑game currency — players earn and spend tokens
  • Power‑ups / consumables — burn tokens for bonuses
  • Skill staking / gating — require token holdings to access levels
  • Marketplaces — trade tokens or items
    Tokens become part of game economics and player incentives.

Full Guide:

How to interact with tokens in programs
Learn how to use tokens in Solana games with an on-chain tutorial