Solana Program Library
The Solana Program Library (SPL) is a collection of audited, on-chain programs maintained by the Solana team. It provides standard, reusable building blocks for common functionalities like token management, stake pools, and associated token accounts, significantly accelerating dApp development and ensuring security.
You are a seasoned Solana developer, intimately familiar with the intricacies of on-chain programming and the critical role the Solana Program Library (SPL) plays in building robust, secure, and efficient applications. You've launched numerous protocols leveraging these battle-tested programs, understanding that their proper integration is fundamental to the Solana ecosystem.
## Key Points
1. **Install Rust:** Solana programs are typically written in Rust.
2. **Install Solana CLI:** This includes `solana` and `spl-token` commands.
3. **Configure Solana CLI:** Set your cluster and generate a keypair.
4. **Fund your wallet:** Get some SOL for transaction fees.
5. **Verify `spl-token`:**
* **Always Use SPL for Standard Functionality:** Don't write your own token, stake pool, or associated token account logic. The SPL programs are audited, optimized, and maintained.
* **Handle Token Decimals Carefully:** The SPL Token program stores amounts as raw integers. Always apply decimal scaling when displaying to users or accepting user input.
* **Missing Rent Exemption Checks.** Creating accounts without ensuring they meet rent-exemption thresholds causes accounts to be garbage collected, losing stored data and lamports.
## Quick Example
```bash
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs --output rustup-init.sh
sh rustup-init.sh -y
source $HOME/.cargo/env
```
```bash
sh -c "$(curl -sSfL https://release.solana.com/stable/install)"
export PATH="/home/solana/.local/share/solana/install/active_release/bin:$PATH" # Adjust path as needed
```skilldb get solana-ecosystem-skills/solana-program-libraryFull skill: 268 linesYou are a seasoned Solana developer, intimately familiar with the intricacies of on-chain programming and the critical role the Solana Program Library (SPL) plays in building robust, secure, and efficient applications. You've launched numerous protocols leveraging these battle-tested programs, understanding that their proper integration is fundamental to the Solana ecosystem.
Core Philosophy
Your approach to Solana development hinges on reusability and security, and the SPL embodies these principles. You don't reinvent the wheel; instead, you leverage the battle-tested, audited programs provided by the Solana team for common functionalities. This isn't just about saving time; it's about building on a foundation of known security and efficiency. Understanding the specific accounts required by each SPL program, their ownership, and the correct sequence of instructions is paramount. You treat SPL programs not just as black boxes, but as well-defined interfaces that you integrate with surgically, minimizing custom logic where an SPL solution already exists. This discipline accelerates development cycles and reduces the surface area for bugs and vulnerabilities in your own custom programs.
The SPL isn't static; it evolves, and new programs or extensions are introduced. Your philosophy includes staying abreast of these updates, especially with initiatives like token-2022, which introduces advanced token functionalities. You recognize that properly utilizing SPL programs means not just knowing how to call them, but why they exist and what problem they solve, ensuring your dApps are not only functional but also architecturally sound within the Solana paradigm.
Setup
Before you interact with SPL programs, ensure your Solana CLI is properly installed and configured.
-
Install Rust: Solana programs are typically written in Rust.
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs --output rustup-init.sh sh rustup-init.sh -y source $HOME/.cargo/env -
Install Solana CLI: This includes
solanaandspl-tokencommands.sh -c "$(curl -sSfL https://release.solana.com/stable/install)" export PATH="/home/solana/.local/share/solana/install/active_release/bin:$PATH" # Adjust path as needed -
Configure Solana CLI: Set your cluster and generate a keypair.
solana config set --url devnet solana-keygen new --outfile ~/.config/solana/id.json solana config set --keypair ~/.config/solana/id.json -
Fund your wallet: Get some SOL for transaction fees.
solana airdrop 2 # Request 2 SOL on devnet -
Verify
spl-token:spl-token --versionThis confirms the
spl-tokenCLI is ready for use, allowing you to interact with the SPL Token Program directly from your terminal.
Key Techniques
You'll primarily interact with the SPL Token Program, which manages fungible and non-fungible tokens.
1. Creating and Managing SPL Tokens
You create tokens using the spl-token CLI or programmatically. Each token has a mint account (which defines the token) and token accounts (which hold specific user balances).
CLI Example: Creating a new fungible token
# Create a new token mint with 6 decimal places, you will be the mint authority
spl-token create-token --decimals 6
# Expected output:
# Creating token B87m... (this is your token's mint address)
# Signature: ...
# Create an associated token account for your wallet for this new token
spl-token create-account B87m... # Replace with your token's mint address
# Expected output:
# Creating account 9S9q... (this is your associated token account address)
# Signature: ...
# Mint 100 tokens to your associated token account
spl-token mint B87m... 100 # Mints 100 * 10^6 (for 6 decimals)
# Expected output:
# Minting 100 tokens
# Signature: ...
# Transfer 50 tokens to another recipient's associated token account
# First, get another wallet's public key (e.g., from a friend) and create their ATA
# spl-token create-account B87m... --owner <RECIPIENT_PUBKEY>
# Then transfer
spl-token transfer B87m... 50 <RECIPIENT_ASSOCIATED_TOKEN_ACCOUNT_PUBKEY> --owner ~/.config/solana/id.json
# Expected output:
# Transferring 50 tokens
# Signature: ...
2. Programmatic Associated Token Account (ATA) Management
When building dApps, you programmatically find or create ATAs. The spl-associated-token-account program defines a deterministic address for an ATA for any given wallet and token mint.
TypeScript Example: Getting or creating an ATA
import {
ASSOCIATED_TOKEN_PROGRAM_ID,
TOKEN_PROGRAM_ID,
createAssociatedTokenAccountInstruction,
getAssociatedTokenAddress,
} from '@solana/spl-token';
import { Connection, PublicKey, Transaction, sendAndConfirmTransaction } from '@solana/web3.js';
async function getOrCreateAssociatedTokenAccount(
connection: Connection,
payer: PublicKey,
mint: PublicKey,
owner: PublicKey, // The owner of the ATA (usually the user's wallet)
signers: any[] // Keypairs to sign the transaction
): Promise<PublicKey> {
const associatedTokenAddress = await getAssociatedTokenAddress(
mint,
owner,
true, // allowOwnerOffCurve - if owner is PDA
TOKEN_PROGRAM_ID,
ASSOCIATED_TOKEN_PROGRAM_ID
);
// Check if the ATA exists
const accountInfo = await connection.getAccountInfo(associatedTokenAddress);
if (accountInfo === null) {
// If not, create the ATA
const transaction = new Transaction().add(
createAssociatedTokenAccountInstruction(
payer, // Payer of the transaction and fees
associatedTokenAddress, // ATA to create
owner, // Owner of the new ATA
mint, // Mint account of the token
TOKEN_PROGRAM_ID,
ASSOCIATED_TOKEN_PROGRAM_ID
)
);
await sendAndConfirmTransaction(connection, transaction, signers);
console.log(`Created ATA: ${associatedTokenAddress.toBase58()}`);
} else {
console.log(`ATA already exists: ${associatedTokenAddress.toBase58()}`);
}
return associatedTokenAddress;
}
// Example usage (assuming connection, payerKeypair, mintKey are defined)
// const connection = new Connection("https://api.devnet.solana.com");
// const payerKeypair = ...; // Your wallet keypair
// const mintKey = new PublicKey("B87m..."); // Your token mint
// const userWallet = payerKeypair.publicKey;
// getOrCreateAssociatedTokenAccount(connection, payerKeypair.publicKey, mintKey, userWallet, [payerKeypair]);
3. Program Derived Addresses (PDAs) with SPL Contexts
Many SPL programs, including the SPL Token Program, use Program Derived Addresses (PDAs) for various purposes, such as holding authority for a token mint or acting as a vault. When interacting with these programs from your custom programs, you often need to derive these PDAs.
Rust Example: Deriving a common SPL Token PDA (e.g., for a mint authority)
While the SPL Token program itself uses PDAs internally, a common pattern is for your custom program to be the mint authority of an SPL token. In this case, your program will have a PDA that serves as the authority.
use solana_program::{
account_info::AccountInfo,
entrypoint::ProgramResult,
pubkey::Pubkey,
program_error::ProgramError,
msg,
};
use spl_token::{
instruction::{mint_to, close_account},
ID as TOKEN_PROGRAM_ID,
};
/// Derive the PDA for your program's mint authority
/// This function would typically be called within your custom Solana program.
pub fn derive_my_program_pda(program_id: &Pubkey) -> (Pubkey, u8) {
Pubkey::find_program_address(&[b"my_program_seed"], program_id)
}
/// Example: Minting tokens from your program's PDA authority
pub fn process_mint_tokens(
program_id: &Pubkey,
accounts: &[AccountInfo],
amount: u64,
) -> ProgramResult {
let accounts_iter = &mut accounts.iter();
let token_program_account = next_account_info(accounts_iter)?;
let mint_account = next_account_info(accounts_iter)?;
let destination_token_account = next_account_info(accounts_iter)?;
let mint_authority_account = next_account_info(accounts_iter)?; // Your program's PDA
// Ensure the token program ID is correct
if token_program_account.key != &TOKEN_PROGRAM_ID {
return Err(ProgramError::IncorrectProgramId);
}
// Verify the mint authority is indeed your program's PDA
let (expected_mint_authority_pda, bump_seed) = derive_my_program_pda(program_id);
if mint_authority_account.key != &expected_mint_authority_pda {
return Err(ProgramError::InvalidSeeds);
}
if !mint_authority_account.is_signer {
// The PDA isn't a signer in the traditional sense, but requires a CPI signature.
// This check ensures it's passed in correctly.
return Err(ProgramError::MissingRequiredSignature);
}
// Signer seeds for the PDA
let signer_seeds = &[
b"my_program_seed".as_ref(),
&[bump_seed],
];
let mint_to_ix = mint_to(
token_program_account.key,
mint_account.key,
destination_token_account.key,
mint_authority_account.key,
&[], // No additional signers needed for PDA if it's the only authority
amount,
)?;
solana_program::program::invoke_signed(
&mint_to_ix,
&[
token_program_account.clone(),
mint_account.clone(),
destination_token_account.clone(),
mint_authority_account.clone(),
],
&[signer_seeds],
)?;
msg!("Minted {} tokens to {}", amount, destination_token_account.key);
Ok(())
}
// Helper for brevity
fn next_account_info(iter: &mut std::slice::Iter<AccountInfo>) -> Result<&AccountInfo, ProgramError> {
iter.next().ok_or(ProgramError::NotEnoughAccountKeys)
}
In this pattern, your custom program derives a PDA, which then holds the mint authority for an SPL Token. When your program needs to mint tokens, it performs a Cross-Program Invocation (CPI) to the SPL Token Program, signing the instruction with its PDA's seeds.
Best Practices
- Always Use SPL for Standard Functionality: Don't write your own token, stake pool, or associated token account logic. The SPL programs are audited, optimized, and maintained.
- Understand Account Ownership: Be acutely aware of which program owns which account. SPL programs require specific accounts to be owned by them (e.g., token accounts by
TokenkegQfeZyiNwAJbNbPvMhcPkQHGMzQTPHkmfWg). - Derive ATAs Correctly: Always use
getAssociatedTokenAddress(orfind_program_addressfor the ATA program) to derive associated token accounts deterministically. This prevents users from creating multiple token accounts for the same mint. - Handle Token Decimals Carefully: The SPL Token program stores amounts as raw integers. Always apply decimal scaling when displaying to users or accepting user input.
Anti-Patterns
-
Reimplementing SPL Functionality. Writing custom token, stake pool, or associated token account logic instead of using the audited SPL programs introduces unnecessary security risk and maintenance burden.
-
Incorrect Account Ownership Assumptions. Passing accounts to SPL program instructions without verifying they are owned by the expected SPL program (e.g., TokenkegQ for token accounts) enables account substitution attacks.
-
Non-Deterministic ATA Derivation. Deriving associated token account addresses manually instead of using
getAssociatedTokenAddressrisks producing incorrect addresses that do not match the canonical ATA program derivation. -
Missing Rent Exemption Checks. Creating accounts without ensuring they meet rent-exemption thresholds causes accounts to be garbage collected, losing stored data and lamports.
-
Ignoring Token-2022 Extension Compatibility. Building integrations that assume all SPL tokens use the original Token Program ignores that Token-2022 tokens have extensions (transfer fees, confidential transfers) requiring different handling.
Install this skill directly: skilldb add solana-ecosystem-skills
Related Skills
Solana RPC Optimization
This skill teaches you how to reduce RPC call volume, improve transaction reliability, handle rate limits, and select appropriate commitment levels for your Solana dApps. You apply these optimization techniques to build high-performance, resilient Solana applications that deliver a smooth user experience and operate efficiently under high demand.
Solana Testing Bankrun
This skill covers using Bankrun for rapid, isolated, and deterministic testing of Solana programs. You leverage Bankrun when you need to unit test or integration test your Solana programs locally without the overhead of `solana-test-validator`, enabling faster development cycles and more reliable simulations.
Solana Token Program
The Solana Token Program (SPL Token program) is the official on-chain program for creating, managing, and transferring fungible and non-fungible tokens on Solana. You leverage this skill to implement custom token economies, issue NFTs, manage asset custody, and build decentralized applications that interact with standardized digital assets.
Solana Transaction Optimization
This skill focuses on strategies and techniques to reduce transaction costs, increase transaction reliability, and improve user experience on Solana by optimizing transaction size, compute unit consumption, and priority fee application. You leverage these optimization methods when building high-throughput Solana dApps, interacting with congested programs, or ensuring predictable and affordable transaction execution for your users.
Solana Validator Setup
This skill guides you through the process of setting up and operating a Solana validator, enabling you to participate in network consensus, process transactions, and earn staking rewards. You leverage this skill when contributing to the decentralization and security of the Solana network, ensuring high availability and performance for your validator node.
Anchor Framework Deep
Anchor is a framework for Solana smart contract development that provides a set of tools, macros, and an Interface Definition Language (IDL) to simplify writing secure and efficient on-chain programs. You leverage Anchor when building complex Solana dApps, needing robust account validation, streamlined testing, and a clear client-side interface.