Compress and Decompress SPL Tokens
Complete guide to compress SPL tokens with compress() and decompress with decompress(), troubleshooting and advanced configurations.
The compress() and decompress() functions convert SPL tokens between compressed and regular format.
Before we convert formats, we need:
An SPL mint with a token pool for compression. This token pool can be created for new SPL mints via
createMint()or added to existing SPL mints viacreateTokenPool().For
compress()SPL tokens in an Associated Token Account, orFor
decompress()compressed token accounts with sufficient balance.
// Compress SPL tokens to compressed tokens
const compressionSignature = await compress(
rpc,
payer,
mint, // SPL mint with token pool for compression
amount,
payer, // owner of SPL tokens
tokenAccount.address, // source SPL token account (sourceTokenAccount parameter)
recipient, // recipient owner address (toAddress parameter)
);// Decompress compressed tokens to SPL tokens
const transactionSignature = await decompress(
rpc,
payer,
mint, // SPL mint with token pool for compression
amount,
payer, // owner of compressed tokens
tokenAccount.address, // destination token account (toAddress parameter)
);Function Difference and Best Practice:
compress(amount, sourceTokenAccount, toAddress)compresses specific amounts from source to a specified recipient. Use for transfers and precise amounts.compressSplTokenAccount(tokenAccount, remainingAmount)compresses the entire SPL token account balance minus optional remaining amount only to the same owner. Use to migrate complete token accounts with optional partial retention. Here is how.
Full Code Example
Compress / Decompress Tokens
Compress SPL tokens to compressed format.
// 1. Setup funded payer and connect to local validator
// 2. Create SPL mint with token pool and mint SPL tokens to ATA
// 3. Call compress() to convert SPL tokens to compressed format
// 4. Verify balances via getTokenAccountBalance and getCompressedTokenAccountsByOwner
import { Keypair } from '@solana/web3.js';
import { createRpc } from '@lightprotocol/stateless.js';
import {
createMint,
compress
} from '@lightprotocol/compressed-token';
import {
getOrCreateAssociatedTokenAccount,
mintTo as splMintTo,
TOKEN_PROGRAM_ID
} from '@solana/spl-token';
import BN from 'bn.js';
async function compressTokens() {
// Step 1: Setup funded payer and connect to local validator
const rpc = createRpc(); // defaults to localhost:8899
const payer = Keypair.generate();
const airdropSignature = await rpc.requestAirdrop(payer.publicKey, 1000000000); // 1 SOL
await rpc.confirmTransaction(airdropSignature);
// Step 2: Create SPL mint with token pool and mint SPL tokens to ATA
const { mint } = await createMint(rpc, payer, payer.publicKey, 9);
console.log("Mint with token pool created:", mint.toBase58());
const tokenOwner = Keypair.generate();
const tokenAccount = await getOrCreateAssociatedTokenAccount(
rpc, payer, mint, tokenOwner.publicKey, false, TOKEN_PROGRAM_ID
);
// Mint SPL tokens to the ATA
const splAmount = 1_000_000_000; // 1 token with 9 decimals
await splMintTo(rpc, payer, mint, tokenAccount.address, payer, splAmount, [], undefined, TOKEN_PROGRAM_ID);
console.log("SPL tokens minted:", splAmount / 1_000_000_000, "tokens");
console.log("Compress Tokens");
const compressAmount = 400_000_000; // 0.4 tokens
// Step 3: Call compress() to convert to compressed format
// Lock SPL tokens to pool account and mint compressed tokens
const compressTx = await compress(
rpc,
payer,
mint, // SPL mint with token pool for compression
compressAmount, // amount to compress
tokenOwner, // owner of SPL tokens
tokenAccount.address, // source token account
tokenOwner.publicKey, // recipient for compressed tokens
);
console.log("Compressed amount:", compressAmount / 1_000_000_000, "tokens");
console.log("Transaction:", compressTx);
// Step 4: Verify balances via getTokenAccountBalance and getCompressedTokenAccountsByOwner
const finalTokenBalance = await rpc.getTokenAccountBalance(tokenAccount.address);
const finalCompressedAccounts = await rpc.getCompressedTokenAccountsByOwner(
tokenOwner.publicKey,
{ mint }
);
// Calculate total compressed balance
const finalCompressedBalance = finalCompressedAccounts.items.reduce(
(sum, account) => sum.add(account.parsed.amount),
new BN(0)
);
console.log("\nFinal balances:");
console.log("Regular SPL tokens:", finalTokenBalance.value.uiAmount);
console.log("Compressed tokens:", finalCompressedBalance.toNumber() / 1_000_000_000);
return {
compressTransaction: compressTx,
finalCompressedBalance,
finalSplBalance: finalTokenBalance.value.amount
};
}
compressTokens().catch(console.error);Compress SPL tokens and decompress in one script.
// 1. Setup funded payer and connect to local validator
// 2. Create SPL mint with token pool and mint SPL tokens to ATA
// 3. Compress SPL tokens to compressed format
// 4. Decompress compressed tokens back to SPL format
// 5. Verify final balances
import { Keypair } from '@solana/web3.js';
import { createRpc } from '@lightprotocol/stateless.js';
import {
createMint,
compress,
decompress
} from '@lightprotocol/compressed-token';
import {
getOrCreateAssociatedTokenAccount,
mintTo as splMintTo,
TOKEN_PROGRAM_ID
} from '@solana/spl-token';
import BN from 'bn.js';
async function compressAndDecompressTokens() {
// Step 1: Setup funded payer and connect to local validator
const rpc = createRpc(); // defaults to localhost:8899
const payer = Keypair.generate();
const airdropSignature = await rpc.requestAirdrop(payer.publicKey, 1000000000); // 1 SOL
await rpc.confirmTransaction(airdropSignature);
// Step 2: Create SPL mint with token pool and mint SPL tokens to ATA
const { mint } = await createMint(rpc, payer, payer.publicKey, 9);
console.log("Mint with token pool created:", mint.toBase58());
const tokenOwner = Keypair.generate();
const tokenAccount = await getOrCreateAssociatedTokenAccount(
rpc, payer, mint, tokenOwner.publicKey, false, TOKEN_PROGRAM_ID
);
// Mint SPL tokens to the ATA
const splAmount = 1_000_000_000; // 1 token with 9 decimals
await splMintTo(rpc, payer, mint, tokenAccount.address, payer, splAmount, [], undefined, TOKEN_PROGRAM_ID);
console.log("SPL tokens minted:", splAmount / 1_000_000_000, "tokens");
console.log("\n=== Compress Tokens ===");
const compressAmount = 600_000_000; // 0.6 tokens
// Step 3: Compress SPL tokens
const compressTx = await compress(
rpc,
payer,
mint,
compressAmount,
tokenOwner,
tokenAccount.address,
tokenOwner.publicKey,
);
console.log("Compressed amount:", compressAmount / 1_000_000_000, "tokens");
console.log("Compress transaction:", compressTx);
// Verify compressed balance
const compressedAccounts = await rpc.getCompressedTokenAccountsByOwner(
tokenOwner.publicKey,
{ mint }
);
const compressedBalance = compressedAccounts.items.reduce(
(sum, account) => sum.add(account.parsed.amount),
new BN(0)
);
console.log("Compressed balance:", compressedBalance.toNumber() / 1_000_000_000, "tokens");
console.log("\n=== Decompress Tokens ===");
const decompressAmount = 300_000_000; // 0.3 tokens
// Step 4: Decompress compressed tokens back to SPL format
const decompressTx = await decompress(
rpc,
payer,
mint,
decompressAmount,
tokenOwner,
tokenAccount.address,
);
console.log("Decompressed amount:", decompressAmount / 1_000_000_000, "tokens");
console.log("Decompress transaction:", decompressTx);
// Step 5: Verify final balances
const finalTokenBalance = await rpc.getTokenAccountBalance(tokenAccount.address);
const finalCompressedAccounts = await rpc.getCompressedTokenAccountsByOwner(
tokenOwner.publicKey,
{ mint }
);
const finalCompressedBalance = finalCompressedAccounts.items.reduce(
(sum, account) => sum.add(account.parsed.amount),
new BN(0)
);
console.log("\n=== Final Balances ===");
console.log("Regular SPL tokens:", finalTokenBalance.value.uiAmount);
console.log("Compressed tokens:", finalCompressedBalance.toNumber() / 1_000_000_000);
return {
compressTransaction: compressTx,
decompressTransaction: decompressTx,
finalCompressedBalance,
finalSplBalance: finalTokenBalance.value.amount
};
}
compressAndDecompressTokens().catch(console.error);Troubleshooting
Advanced Configurations
Next Steps
Learn how to compress complete token accounts in one transaction and reclaim rent afterwards.
Compress Complete SPL Token AccountsLast updated
Was this helpful?