Best Practices
- Clear UI Indicators — Provide clear visual distinctions between compressed and uncompressed SPL tokens
- Transaction History — Provide detailed transaction histories for compressed tokens
- Decompression and Compression — Provide a clear path for users to convert between compressed and uncompressed tokens when needed
Leading Solana Wallets like Phantom and Backpack already support compressed tokens.
Integration Steps
- Code Snippets
- End-to-End Guide
Display Compressed Token Balances
Copy
Ask AI
import { Rpc, createRpc } from '@lightprotocol/stateless.js';
import { PublicKey } from '@solana/web3.js';
const connection: Rpc = createRpc();
const publicKey = new PublicKey('CLEuMG7pzJX9xAuKCFzBP154uiG1GaNo4Fq7x6KAcAfG');
(async () => {
const balances = await connection.getCompressedTokenBalancesByOwnerV2(publicKey);
console.log(balances);
})();
Get Transaction History
Copy
Ask AI
import { Rpc, createRpc } from '@lightprotocol/stateless.js';
import { PublicKey } from '@solana/web3.js';
const connection: Rpc = createRpc();
const publicKey = new PublicKey('CLEuMG7pzJX9xAuKCFzBP154uiG1GaNo4Fq7x6KAcAfG');
(async () => {
const signatures = await connection.getCompressionSignaturesForOwner(publicKey);
console.log(signatures);
if (signatures.items.length > 0) {
const parsedTransaction = await connection.getTransactionWithCompressionInfo(signatures.items[0].signature);
console.log(parsedTransaction);
}
})();
Send Compressed Tokens
send-compressed-tokens.ts
Copy
Ask AI
import {
Rpc,
createRpc,
bn,
dedupeSigner,
sendAndConfirmTx,
buildAndSignTx,
} from "@lightprotocol/stateless.js";
import {
CompressedTokenProgram,
selectMinCompressedTokenAccountsForTransfer,
} from "@lightprotocol/compressed-token";
import { ComputeBudgetProgram, Keypair, PublicKey } from "@solana/web3.js";
const connection: Rpc = createRpc();
const mint = new PublicKey("MINT_ADDRESS");
const payer = PAYER_KEYPAIR;
const owner = payer;
const recipient = Keypair.generate();
const amount = bn(1e8);
(async () => {
const compressedTokenAccounts =
await connection.getCompressedTokenAccountsByOwner(owner.publicKey, { mint });
if (compressedTokenAccounts.items.length === 0) {
console.log("No compressed token accounts found");
return;
}
const [inputAccounts] = selectMinCompressedTokenAccountsForTransfer(
compressedTokenAccounts.items,
amount
);
const proof = await connection.getValidityProof(
inputAccounts.map((account) => account.compressedAccount.hash)
);
const ix = await CompressedTokenProgram.transfer({
payer: payer.publicKey,
inputCompressedTokenAccounts: inputAccounts,
toAddress: recipient.publicKey,
amount,
recentInputStateRootIndices: proof.rootIndices,
recentValidityProof: proof.compressedProof,
});
const { blockhash } = await connection.getLatestBlockhash();
const additionalSigners = dedupeSigner(payer, [owner]);
const signedTx = buildAndSignTx(
[ComputeBudgetProgram.setComputeUnitLimit({ units: 300_000 }), ix],
payer,
blockhash,
additionalSigners
);
const transferTxId = await sendAndConfirmTx(connection, signedTx);
console.log(`Transaction: ${transferTxId}`);
})();
Advanced Integrations
Use these integrations to let users convert between regular and compressed format as needed.Decompress to Regular SPL
Decompress to Regular SPL
This example converts compressed tokens to regular SPL format using
CompressedTokenProgram.decompress().Copy
Ask AI
import {
bn,
buildAndSignTx,
sendAndConfirmTx,
dedupeSigner,
Rpc,
createRpc,
} from "@lightprotocol/stateless.js";
import { ComputeBudgetProgram } from "@solana/web3.js";
import {
CompressedTokenProgram,
getTokenPoolInfos,
selectMinCompressedTokenAccountsForTransfer,
selectTokenPoolInfosForDecompression,
} from "@lightprotocol/compressed-token";
// 1. Setup RPC connection and fetch compressed token accounts with getCompressedTokenAccountsByOwner()
// 2. Select accounts and token pool infos using selectMinCompressedTokenAccountsForTransfer() and selectTokenPoolInfosForDecompression()
// 3. Create decompress instruction with CompressedTokenProgram.decompress() and submit transaction
// Step 1: Setup RPC connection and define decompression parameters
const connection: Rpc = createRpc("https://mainnet.helius-rpc.com?api-key=<api_key>";);
const payer = PAYER_KEYPAIR;
const owner = PAYER_KEYPAIR;
const mint = MINT_ADDRESS;
const amount = 1e5; // 100K tokens to decompress
(async () => {
// 1. Fetch compressed token accounts
const compressedTokenAccounts =
await connection.getCompressedTokenAccountsByOwner(owner.publicKey, {
mint,
});
// 2. Select
const [inputAccounts] = selectMinCompressedTokenAccountsForTransfer(
compressedTokenAccounts.items,
bn(amount)
);
// 3. Fetch validity proof
const proof = await connection.getValidityProof(
inputAccounts.map((account) => account.compressedAccount.hash)
);
// 4. Fetch & Select tokenPoolInfos
const tokenPoolInfos = await getTokenPoolInfos(connection, mint);
const selectedTokenPoolInfos = selectTokenPoolInfosForDecompression(
tokenPoolInfos,
amount
);
// 5. Build instruction
const ix = await CompressedTokenProgram.decompress({
payer: payer.publicKey,
inputCompressedTokenAccounts: inputAccounts,
toAddress: owner.publicKey,
amount,
tokenPoolInfos: selectedTokenPoolInfos,
recentInputStateRootIndices: proof.rootIndices,
recentValidityProof: proof.compressedProof,
});
// 6. Sign, send, and confirm.
// Example with keypair:
const { blockhash } = await connection.getLatestBlockhash();
const additionalSigners = dedupeSigner(payer, [owner]);
const signedTx = buildAndSignTx(
[ComputeBudgetProgram.setComputeUnitLimit({ units: 300_000 }), ix],
payer,
blockhash,
additionalSigners
);
return await sendAndConfirmTx(connection, signedTx);
})();
Compress Regular SPL Tokens
Compress Regular SPL Tokens
This example converts regular SPL tokens to compressed format using
CompressedTokenProgram.compress().Copy
Ask AI
// 1. Setup RPC connection and get user ATA with getOrCreateAssociatedTokenAccount()
// 2. Fetch state tree and token pool infos using getStateTreeInfos() and getTokenPoolInfos()
// 3. Create compress instruction with CompressedTokenProgram.compress() and submit transaction
import {
buildAndSignTx,
sendAndConfirmTx,
Rpc,
createRpc,
selectStateTreeInfo,
} from "@lightprotocol/stateless.js";
import { ComputeBudgetProgram } from "@solana/web3.js";
import {
CompressedTokenProgram,
getTokenPoolInfos,
selectTokenPoolInfo,
} from "@lightprotocol/compressed-token";
import { getOrCreateAssociatedTokenAccount } from "@solana/spl-token";
// Step 1: Setup RPC connection and define compression parameters
const connection: Rpc = createRpc(
"https://mainnet.helius-rpc.com?api-key=<api_key>"
);
const payer = <PAYER_KEYPAIR>;
const mint = <MINT_ADDRESS>;
const amount = 1e5; // 100K tokens to compress
(async () => {
// Step 2: Get or create associated token account for SPL tokens
const sourceTokenAccount = await getOrCreateAssociatedTokenAccount(
connection,
payer, // fee payer
mint, // token mint address
payer.publicKey // token account owner
);
// Step 3: Fetch and select state tree info for compression
const treeInfos = await connection.getStateTreeInfos();
const treeInfo = selectStateTreeInfo(treeInfos);
// Step 4: Fetch and select token pool info for compression
const tokenPoolInfos = await getTokenPoolInfos(connection, mint);
const tokenPoolInfo = selectTokenPoolInfo(tokenPoolInfos);
// Step 5: Create compress instruction - transfer SPL tokens to pool and create compressed accounts
const compressInstruction = await CompressedTokenProgram.compress({
payer: payer.publicKey, // fee payer
owner: payer.publicKey, // owner of source SPL tokens
source: sourceTokenAccount.address, // source ATA address
toAddress: payer.publicKey, // recipient of compressed tokens (self)
amount, // amount to compress
mint, // token mint address
outputStateTreeInfo: treeInfo, // state tree for compressed accounts
tokenPoolInfo, // token pool for compression
});
// Step 6: Build, sign, and submit compression transaction
const { blockhash } = await connection.getLatestBlockhash();
const tx = buildAndSignTx(
[
ComputeBudgetProgram.setComputeUnitLimit({ units: 300_000 }),
compressInstruction,
],
payer, // transaction signer
blockhash,
[payer] // additional signers
);
await sendAndConfirmTx(connection, tx);
})();
Common Errors
No compressed tokens found
No compressed tokens found
If
getCompressedTokenBalancesByOwnerV2 returns empty:- Ensure the wallet has compressed tokens (not regular SPL tokens)
- Verify you’re on the correct network (devnet/mainnet)