The Light SDK sponsors rent-exemption for Solana accounts and keeps accounts active through periodic top-ups paid by the fee payer. Sponsor top-ups by setting your application as the fee payer to abstract away holding SOL from your users or provide a rent-free experience similar to transaction fee sponsorship.
Prerequisite: How Rent Sponsorship works
Rent sponsorship is a built-in feature of the Light SDK’s that sponsors rent-exemption for all account types to reduce creation cost.
This is dealt with under the hood in a way that doesn’t disrupt the UX of what your users are used to with SPL-token.Rent-exemption: sponsored by a rent sponsor PDA.Every Solana account requires a rent-exempt balance in SOL upon creation.
A rent sponsor PDA by Light Protocol pays the rent-exemption cost for the account so account creators never lock up SOL for rent.Top-ups: paid by the fee payer.The feePayer on the transaction bumps a small virtual rent balance (766 lamports by default)
on each write to keep the account active (hot balance).
If you’re building a wallet or dApp, set your application as the fee payer and your users never pay rent or top-ups.
“Cold” accounts virtual rent balance below threshold (eg 24h without write bump) get auto-compressed.
The cold account’s state is cryptographically preserved on the Solana ledger.
Users can load a cold account into hot state in-flight when using the account again.
Report incorrect code
Copy
Ask AI
Rent sponsor PDA Fee payer bumps pays rent-exemption virtual rent on write │ │ ▼ │ ┌─────────┐ ┌────┴────┐ │ CREATE │ ──────────────────►│ HOT │◄───┐ └─────────┘ └────┬────┘ │ │ │ no writes for │ client loads threshold │ cold → hot (e.g. 24h) │ │ │ ▼ │ ┌─────────┐ │ │ COLD │────┘ └─────────┘
How to use Sponsored Rent Top-Ups for Accounts and Transfers
To sponsor rent top-ups for your users, set the payer parameter to the sponsor’s public key when calling createTransferInterfaceInstructions (TypeScript) or building a TransferInterface instruction (Rust). The sponsor pays SOL for any rent top-ups while the user only signs to authorize the transfer.
You can set the payer to any signing account on any Light Token transaction.
TypeScript Client
Rust Client
AI Prompt
Report incorrect code
Copy
Ask AI
import { Keypair, Transaction, sendAndConfirmTransaction } from "@solana/web3.js";import { createRpc } from "@lightprotocol/stateless.js";import { createAtaInterface, createLightTokenTransferInstruction, getAssociatedTokenAddressInterface,} from "@lightprotocol/compressed-token";import { PublicKey } from "@solana/web3.js";const rpc = createRpc();// Top-Up Sponsor: your application server, pays SOL for rent top-upsconst sponsor: Keypair = /* your server keypair */;// User: only signs to authorize the transferconst sender: Keypair = /* user's keypair */;const recipient = new PublicKey(/* recipient address */);const mint = new PublicKey(/* e.g. USDC mint */);(async function () { const senderAta = getAssociatedTokenAddressInterface(mint, sender.publicKey); const recipientAta = getAssociatedTokenAddressInterface(mint, recipient); // Create recipient associated token account if it doesn't exist await createAtaInterface(rpc, sponsor, mint, recipient); const ix = createLightTokenTransferInstruction( senderAta, recipientAta, sender.publicKey, 500_000, sponsor.publicKey, ); const tx = new Transaction().add(ix); const sig = await sendAndConfirmTransaction(rpc, tx, [sponsor, sender]); console.log("Tx:", sig);})();
Report incorrect code
Copy
Ask AI
use light_client::rpc::Rpc;use light_program_test::{LightProgramTest, ProgramTestConfig};use light_token::instruction::{ get_associated_token_address, CreateAssociatedTokenAccount, TransferInterface, LIGHT_TOKEN_PROGRAM_ID,};use solana_sdk::{pubkey::Pubkey, signature::Keypair, signer::Signer};#[tokio::main]async fn main() -> Result<(), Box<dyn std::error::Error>> { let mut rpc = LightProgramTest::new(ProgramTestConfig::new_v2(true, None)).await?; // Top-Up Sponsor: your application server, pays SOL for rent top-ups let sponsor = rpc.get_payer().insecure_clone(); // User: only signs to authorize the transfer let sender: Keypair = /* user's keypair */; let recipient: Pubkey = /* recipient address */; let mint: Pubkey = /* e.g. USDC mint */; let decimals = 6u8; let sender_ata = get_associated_token_address(&sender.pubkey(), &mint); let recipient_ata = get_associated_token_address(&recipient, &mint); // Create recipient associated token account if it doesn't exist let create_ata_ix = CreateAssociatedTokenAccount::new(sponsor.pubkey(), recipient, mint).instruction()?; rpc.create_and_send_transaction(&[create_ata_ix], &sponsor.pubkey(), &[&sponsor]) .await?; let transfer_ix = TransferInterface { source: sender_ata, destination: recipient_ata, amount: 500_000, decimals, authority: sender.pubkey(), payer: sponsor.pubkey(), spl_interface: None, source_owner: LIGHT_TOKEN_PROGRAM_ID, destination_owner: LIGHT_TOKEN_PROGRAM_ID, } .instruction()?; let sig = rpc .create_and_send_transaction(&[transfer_ix], &sponsor.pubkey(), &[&sponsor, &sender]) .await?; println!("Tx: {sig}"); Ok(())}
---description: Sponsor rent top-ups for Light Token usersallowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression---## Sponsor rent top-ups for Light Token usersContext:- Guide: https://zkcompression.com/light-token/toolkits/sponsor-top-ups- Skills and resources index: https://zkcompression.com/skill.md- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison- Dedicated skill: https://github.com/Lightprotocol/skills/tree/main/skills/payments-and-wallets- Packages: @lightprotocol/compressed-token, @lightprotocol/stateless.jsHow rent sponsorship works:- A rent sponsor PDA pays the rent-exemption cost on account creation so creators never lock up SOL- The fee payer bumps a small virtual rent balance (766 lamports) on each write to keep the account active (hot)- Set your application as the fee payer so users never pay rent or top-upsKey APIs:| Language | Function | Payer parameter || TypeScript | createLightTokenTransferInstruction() | 5th argument: `sponsor.publicKey` || TypeScript | createAtaInterface() | 2nd argument: `sponsor` (Keypair) || Rust | TransferInterface { ..., payer: sponsor.pubkey() } | `payer` field || Rust | CreateAssociatedTokenAccount::new(sponsor, ...) | 1st argument: sponsor pubkey |### 1. Index project- Grep `feePayer|payer|createTransferInstruction|createLightTokenTransferInstruction|@lightprotocol|@solana/spl-token|Connection` across src/- Glob `**/*.ts` and `**/*.tsx` for project structure- Identify: existing token operations, RPC config, fee payer setup, signing flow- Check package.json for existing @lightprotocol/* dependencies- Task subagent (Grep/Read/WebFetch) if project has multiple packages to scan in parallel### 2. Read references- WebFetch the guide above — review TypeScript and Rust code examples- WebFetch skill.md — check for a dedicated skill and resources matching this task- TaskCreate one todo per phase below to track progress### 3. Clarify intention- AskUserQuestion: what is the goal? (add sponsored top-ups to existing light-token code, new integration from scratch, migrate from user-pays to sponsor-pays)- AskUserQuestion: TypeScript or Rust client?- AskUserQuestion: which operations need sponsoring? (transfers only, ATA creation + transfers, all write operations)- Summarize findings and wait for user confirmation before implementing### 4. Create plan- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes- Key pattern: set the `payer` parameter to the sponsor's public key on transfer and ATA creation instructions- The sponsor Keypair must sign the transaction alongside the user- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion)- Present the plan to the user for approval before proceeding### 5. Implement- Add deps if missing: Bash `npm install @lightprotocol/compressed-token @lightprotocol/stateless.js`- Set up RPC: `createRpc(RPC_ENDPOINT)` with a ZK Compression endpoint (Helius, Triton)- Import from `@lightprotocol/compressed-token` for the token APIs- Set sponsor as payer: `createLightTokenTransferInstruction(senderAta, recipientAta, sender.publicKey, amount, sponsor.publicKey)`- Sign with both sponsor and sender: `sendAndConfirmTransaction(rpc, tx, [sponsor, sender])`- Follow the guide and the approved plan- Write/Edit to create or modify files- TaskUpdate to mark each step done### 6. Verify- Bash `tsc --noEmit`- Bash run existing test suite if present- TaskUpdate to mark complete### Tools- mcp__zkcompression__SearchLightProtocol("<query>") for API details- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "<q>") for architecture- Task subagent with Grep/Read/WebFetch for parallel lookups- TaskList to check remaining work