How to Compress complete SPL Token Accounts
Complete guide to compress complete SPL Token Accounts with `compressSplTokenAccount`, troubleshooting and advanced configurations. Use for account migration and to reclaim rent afterwards.
The compressSplTokenAccount
function compresses the balance of an SPL token account, with an optional remainingAmount
parameter to leave tokens in the original account.
The function
Transfer SPL tokens from ATA to token pool account (omnibus account)
Create equivalent compressed accounts for the account owner
Before compressing SPL token accounts, you need:
SPL mint registered with the compressed token program via
createMint()
orcreateTokenPool()
SPL token account (ATA) with tokens to compress
After compression, empty token accounts can now be closed to reclaim rent with closeAccount()
.
Function Difference and Best Practice:
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.compress(amount, sourceTokenAccount, toAddress)
compresses specific amounts from source to a specified recipient. Use for transfers and precise amounts. Here is how.
import { compressSplTokenAccount } from '@lightprotocol/compressed-token';
import { Keypair, PublicKey } from '@solana/web3.js';
import { bn } from '@lightprotocol/stateless.js';
const mint = new PublicKey("YOUR_MINT_ADDRESS");
const owner = payer; // Account owner (signer)
const tokenAccount = new PublicKey("YOUR_TOKEN_ACCOUNT_ADDRESS");
const remainingAmount = bn(100_000_000); // Optional: amount to keep uncompressed
// Transfers SPL tokens to omnibus pool and mints compressed tokens,
const transactionSignature = await compressSplTokenAccount(
rpc,
payer,
mint, // SPL mint with token pool for compression
owner,
tokenAccount, // SPL token account to compress
remainingAmount, // optional amount to keep in SPL format
);
Full Code Example
Compressing SPL Token Accounts
Run this script to compress an entire SPL token account!
// 1. Setup funded payer and connect to local validator
// 2. Create SPL token account with tokens
// 3. Call compressSplTokenAccount() to convert SPL tokens to compressed format
// 4. Verify results via getTokenAccountBalance and getCompressedTokenAccountsByOwner
// 5. Optional: reclaim rent for empty token accounts
import { Keypair, PublicKey } from '@solana/web3.js';
import { createRpc, bn } from '@lightprotocol/stateless.js';
import {
createMint,
compressSplTokenAccount
} from '@lightprotocol/compressed-token';
import {
createAssociatedTokenAccount,
mintTo,
getAssociatedTokenAddress,
TOKEN_PROGRAM_ID
} from '@solana/spl-token';
async function compressSplTokenAccounts() {
// 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 token account with tokens
let { mint, tokenAccount, tokenOwner } = await setup();
// Check balances before compression - SPL account and compressed token accounts
const splBalanceBefore = await rpc.getTokenAccountBalance(tokenAccount);
const compressedAccountsBefore = await rpc.getCompressedTokenAccountsByOwner(
tokenOwner.publicKey,
{ mint }
);
console.log("\nBefore Compression:");
console.log("SPL token balance:", Number(splBalanceBefore.value.amount) / 1_000_000_000, "tokens");
console.log("Compressed accounts:", compressedAccountsBefore.items.length);
// Step 3: Call compressSplTokenAccount() to convert SPL tokens to compressed format
// Transfer SPL tokens to omnibus pool and mint compressed tokens
const compressTx = await compressSplTokenAccount(
rpc,
payer,
mint, // mint with existing token pool
tokenOwner,
tokenAccount, // SPL token account to be compressed
);
console.log("SPL token account compressed!");
console.log("Transaction:", compressTx);
// Step 4: Verify SPL and compressed token account balance
const splBalanceAfter = await rpc.getTokenAccountBalance(tokenAccount);
const compressedAccountsAfter = await rpc.getCompressedTokenAccountsByOwner(
tokenOwner.publicKey,
{ mint }
);
console.log("\nAfter Compression:");
console.log("SPL token balance:", Number(splBalanceAfter.value.amount) / 1_000_000_000, "tokens");
console.log("Compressed accounts:", compressedAccountsAfter.items.length);
// Calculate total compressed balance from all compressed accounts
const totalCompressed = compressedAccountsAfter.items.reduce(
(sum, account) => sum.add(account.parsed.amount),
bn(0)
);
console.log("Total compressed balance:", totalCompressed.toNumber() / 1_000_000_000, "tokens");
// Check if SPL account can be closed for rent reclaim
if (Number(splBalanceAfter.value.amount) === 0) {
console.log("SPL token account is now empty and can be closed to reclaim rent!");
}
console.log("Transaction signature:", compressTx);
return {
compressTransaction: compressTx,
tokenAccount,
splBalanceAfter: Number(splBalanceAfter.value.amount),
compressedBalance: totalCompressed.toNumber()
};
async function setup() {
const { mint } = await createMint(
rpc,
payer,
payer.publicKey,
9,
);
console.log("Compressed mint created:", mint.toBase58());
const tokenOwner = Keypair.generate();
const tokenAccount = await createAssociatedTokenAccount(
rpc,
payer,
mint,
tokenOwner.publicKey,
);
console.log("SPL token account created:", tokenAccount.toBase58());
const mintAmount = 2_000_000_000;
await mintTo(
rpc,
payer,
mint,
tokenAccount,
payer,
mintAmount,
);
console.log("SPL tokens minted:", mintAmount / 1_000_000_000, "tokens");
return {
mint,
tokenAccount,
tokenOwner,
};
}
}
compressSplTokenAccounts().catch(console.error);
Success!
You've compressed an SPL token account. The output shows:
Account compression: Entire SPL token account balance converted to compressed format.
Balance verification: All tokens migrated from SPL account to compressed accounts.
Rent Reclaimable: The empty SPL account can now be closed to reclaim rent with
closeAccount()
.
Troubleshooting
Advanced Configuration
Next Steps
Learn how to merge multiple compressed token accounts into one to simplify state management.
How to Merge Compressed Token AccountsLast updated
Was this helpful?