> ## Documentation Index
> Fetch the complete documentation index at: https://www.zkcompression.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Overview

> Overview to compressed tokens and guides with full code examples. Use for distributing tokens (eg rewards, airdrops) or creating associated token accounts for users.

export const TokenAccountCompressedVsSpl = () => {
  const [numAccounts, setNumAccounts] = useState(100000);
  const [showCustomAccounts, setShowCustomAccounts] = useState(false);
  const ACCOUNT_STORAGE_OVERHEAD = 128;
  const LAMPORTS_PER_BYTE = 6960;
  const DATA_LEN = 165;
  const COMPRESSED_COST_PER_ACCOUNT = 10300;
  const LAMPORTS_PER_SOL = 1_000_000_000;
  const ACCOUNTS_MAX = 1000000;
  const solanaCost = numAccounts * (ACCOUNT_STORAGE_OVERHEAD + DATA_LEN) * LAMPORTS_PER_BYTE;
  const compressedCost = numAccounts * COMPRESSED_COST_PER_ACCOUNT;
  const savings = solanaCost - compressedCost;
  const savingsPercent = (savings / solanaCost * 100).toFixed(1);
  const handleAccountsChange = value => {
    const num = Math.max(1, Math.min(1000000, Number.parseInt(value) || 1));
    setNumAccounts(num);
  };
  const formatSOL = lamports => {
    const sol = lamports / LAMPORTS_PER_SOL;
    if (sol >= 1000) {
      return sol.toLocaleString(undefined, {
        maximumFractionDigits: 2
      });
    } else if (sol >= 1) {
      return sol.toFixed(4);
    }
    return sol.toFixed(6);
  };
  const accountsPresets = [10000, 100000, 500000];
  const SliderMarkers = ({max, step}) => {
    const marks = [];
    for (let i = step; i < max; i += step) {
      const percent = i / max * 100;
      marks.push(<div key={i} className="absolute top-1/2 -translate-y-1/2 w-px h-2 bg-zinc-300 dark:bg-white/30" style={{
        left: `${percent}%`
      }} />);
    }
    return <>{marks}</>;
  };
  return <div className="p-5 rounded-3xl not-prose mt-4 dark:bg-white/5 backdrop-blur-xl border border-black/[0.04] dark:border-white/10 shadow-lg" style={{
    fontFamily: "Inter, sans-serif"
  }}>
      <div className="space-y-5">
        {}
        <div className="space-y-2 px-3">
          <div className="flex justify-between items-center">
            <span className="text-sm text-zinc-700 dark:text-white/80">
              Number of Token Accounts
            </span>
            <div className="flex items-center gap-1.5">
              {accountsPresets.map(a => <button key={a} onClick={() => {
    setNumAccounts(a);
    setShowCustomAccounts(false);
  }} className={`px-2.5 py-1 text-xs font-medium rounded-lg border backdrop-blur-sm transition-all ${numAccounts === a && !showCustomAccounts ? "bg-blue-500/20 border-blue-500/50 text-blue-600 dark:text-blue-400" : "bg-black/[0.015] dark:bg-white/5 border-black/[0.04] dark:border-white/20 text-zinc-600 dark:text-white/70 hover:bg-black/[0.03]"}`}>
                  {a.toLocaleString()}
                </button>)}
              {showCustomAccounts ? <input type="number" min="1" max="1000000" value={numAccounts} onChange={e => handleAccountsChange(e.target.value)} className="w-24 px-2 py-1 text-right text-xs font-mono font-medium bg-blue-500/10 dark:bg-blue-500/20 border border-blue-500/50 rounded-lg backdrop-blur-sm focus:outline-none focus:ring-2 focus:ring-blue-500/50" autoFocus /> : <button onClick={() => setShowCustomAccounts(true)} className="px-2.5 py-1 text-xs font-medium rounded-lg border backdrop-blur-sm transition-all bg-black/[0.015] dark:bg-white/5 border-black/[0.04] dark:border-white/20 text-zinc-600 dark:text-white/70 hover:bg-black/[0.03]">
                  Custom
                </button>}
            </div>
          </div>
          <div className="flex items-center">
            <span className="w-1/3 text-xs text-zinc-500 dark:text-white/50 whitespace-nowrap">
              {numAccounts.toLocaleString()} accounts
            </span>
            <div className="w-2/3 relative">
              <SliderMarkers max={ACCOUNTS_MAX} step={200000} />
              <input type="range" min="5000" max={ACCOUNTS_MAX} step="5000" value={Math.min(numAccounts, ACCOUNTS_MAX)} onChange={e => {
    setNumAccounts(Number.parseInt(e.target.value));
    setShowCustomAccounts(false);
  }} className="relative w-full h-1.5 bg-black/[0.03] dark:bg-white/20 rounded-full appearance-none cursor-pointer backdrop-blur-sm z-10" />
            </div>
          </div>
        </div>

        {}
        <div className="grid grid-cols-3 gap-3">
          <div className="p-4 bg-black/[0.015] dark:bg-white/5 backdrop-blur-md rounded-2xl text-center border border-black/[0.04] dark:border-white/10 shadow-sm">
            <div className="text-xs text-zinc-500 dark:text-white/50 mb-1 uppercase tracking-wide">
              SPL Token
            </div>
            <div className="text-xl font-mono font-semibold text-zinc-900 dark:text-white">
              {formatSOL(solanaCost)}
            </div>
            <div className="text-xs text-zinc-400 dark:text-white/40">SOL</div>
          </div>

          <div className="p-4 bg-black/[0.015] dark:bg-white/5 backdrop-blur-md rounded-2xl text-center border border-black/[0.04] dark:border-white/10 shadow-sm">
            <div className="text-xs text-zinc-500 dark:text-white/50 mb-1 uppercase tracking-wide">
              Compressed
            </div>
            <div className="text-xl font-mono font-semibold text-zinc-900 dark:text-white">
              {formatSOL(compressedCost)}
            </div>
            <div className="text-xs text-zinc-400 dark:text-white/40">SOL</div>
          </div>

          <div className="p-4 bg-black/[0.015] dark:bg-white/5 backdrop-blur-md rounded-2xl text-center border border-black/[0.04] dark:border-white/10 shadow-sm">
            <div className="text-xs text-zinc-500 dark:text-white/50 mb-1 uppercase tracking-wide">
              Savings
            </div>
            <div className="text-xl font-mono font-semibold text-zinc-900 dark:text-white">
              {savingsPercent}%
            </div>
            <div className="text-xs text-zinc-400 dark:text-white/40">{formatSOL(savings)} SOL</div>
          </div>
        </div>
      </div>
    </div>;
};

<Check>
  **Compressed Tokens are supported by leading Solana wallets such as Phantom and Backpack.**
</Check>

| Creation          | Solana               | Compressed         |
| :---------------- | :------------------- | :----------------- |
| **Token Account** | \~2,000,000 lamports | **5,000** lamports |

1. Compressed token accounts store token balance, owner, and other information for SPL and Token 2022 mints.
2. Compressed token accounts are rent-free.
3. Any SPL or Token 2022 token can be compressed and decompressed at will.

## Recommended Usage of Compressed Tokens

<Card title="Token Distribution">
  Distribute tokens without paying upfront rent per recipient.

  <Card title="Create an Airdrop" icon="chevron-right" color="#0066ff" href="/compressed-tokens/token-distribution" horizontal />
</Card>

<Card title="Store SPL-token accounts rent-free">
  Compress existing SPL-token accounts to save rent costs for your users.

  <Card title="Compress SPL Token Accounts" icon="chevron-right" color="#0066ff" href="/compressed-tokens/guides/compress-spl-token-account" horizontal />
</Card>

# Get Started

<Accordion title="Installation & Setup">
  <Steps>
    <Step>
      ### Install dependencies

      <Tabs>
        <Tab title="npm">
          ```bash theme={null}
          npm install @lightprotocol/stateless.js@^0.23.0 \
                      @lightprotocol/compressed-token@^0.23.0
          ```
        </Tab>

        <Tab title="yarn">
          ```bash theme={null}
          yarn add @lightprotocol/stateless.js@^0.23.0 \
                   @lightprotocol/compressed-token@^0.23.0
          ```
        </Tab>

        <Tab title="pnpm">
          ```bash theme={null}
          pnpm add @lightprotocol/stateless.js@^0.23.0 \
                   @lightprotocol/compressed-token@^0.23.0
          ```
        </Tab>

        <Tab title="SDK 2.0 (token-interface)">
          ```bash theme={null}
          # npm
          npm install @lightprotocol/stateless.js@^0.23.0 \
                      @lightprotocol/token-interface@^0.1.2

          # yarn
          yarn add @lightprotocol/stateless.js@^0.23.0 \
                   @lightprotocol/token-interface@^0.1.2

          # pnpm
          pnpm add @lightprotocol/stateless.js@^0.23.0 \
                   @lightprotocol/token-interface@^0.1.2
          ```
        </Tab>
      </Tabs>
    </Step>

    <Step>
      ### Set up your developer environment

      <Tabs>
        <Tab title="Localnet">
          By default, all guides use Localnet.

          <Tabs>
            <Tab title="npm">
              ```bash theme={null}
              npm install -g @lightprotocol/zk-compression-cli
              ```
            </Tab>

            <Tab title="yarn">
              ```bash theme={null}
              yarn global add @lightprotocol/zk-compression-cli
              ```
            </Tab>

            <Tab title="pnpm">
              ```bash theme={null}
              pnpm add -g @lightprotocol/zk-compression-cli
              ```
            </Tab>
          </Tabs>

          ```bash theme={null}
          # Start a local test validator
          light test-validator

          ## ensure you have the Solana CLI accessible in your system PATH
          ```

          ```typescript theme={null}
          // createRpc() defaults to local test validator endpoints
          import {
            Rpc,
            createRpc,
          } from "@lightprotocol/stateless.js";

          const connection: Rpc = createRpc();

          async function main() {
            let slot = await connection.getSlot();
            console.log(slot);

            let health = await connection.getIndexerHealth(slot);
            console.log(health);
            // "Ok"
          }

          main();
          ```
        </Tab>

        <Tab title="Devnet">
          Replace `<your-api-key>` with your actual API key. [Get your API key here](https://www.helius.dev/zk-compression), if you don't have one yet.

          ```typescript theme={null}
          import { createRpc } from "@lightprotocol/stateless.js";

          const RPC_ENDPOINT = "https://devnet.helius-rpc.com?api-key=<your_api_key>";
          const connection = createRpc(RPC_ENDPOINT);

          async function main() {
            let slot = await connection.getSlot();
            console.log(slot);

            let health = await connection.getIndexerHealth(slot);
            console.log(health);
            // "Ok"
          }

          main();
          ```
        </Tab>
      </Tabs>
    </Step>
  </Steps>
</Accordion>

<Steps>
  <Step>
    ### Basic Guides

    | Guide                                                                                                                                   | Description                                                        |
    | :-------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------- |
    | [Create Compressed Token Accounts](https://github.com/Lightprotocol/examples-zk-compression/tree/main/compressed-token-cookbook)        | Create compressed and learn difference to regular token accounts   |
    | [Mint Compressed Tokens](https://github.com/Lightprotocol/examples-zk-compression/tree/main/compressed-token-cookbook)                  | Create new compressed tokens to existing mint                      |
    | [Transfer Compressed Tokens](https://github.com/Lightprotocol/examples-zk-compression/tree/main/compressed-token-cookbook)              | Move compressed tokens between compressed accounts                 |
    | [Decompress and Compress Tokens](https://github.com/Lightprotocol/examples-zk-compression/tree/main/compressed-token-cookbook)          | Convert SPL tokens between regular and compressed format           |
    | [Compress Complete SPL Token Accounts](https://github.com/Lightprotocol/examples-zk-compression/tree/main/compressed-token-cookbook)    | Compress complete SPL token accounts and reclaim rent afterwards   |
    | [Create a Mint with Interface PDA](https://github.com/Lightprotocol/examples-zk-compression/tree/main/compressed-token-cookbook)        | Create new SPL mint with SPL Interface PDA for compression         |
    | [Create SPL Interface for Existing Mints](https://github.com/Lightprotocol/examples-zk-compression/tree/main/compressed-token-cookbook) | Create SPL Interface PDA for existing SPL mints                    |
    | [Merge Compressed Accounts](https://github.com/Lightprotocol/examples-zk-compression/tree/main/compressed-token-cookbook)               | Consolidate multiple compressed accounts of the same mint into one |
    | [Approve and Revoke Delegate Authority](https://github.com/Lightprotocol/examples-zk-compression/tree/main/compressed-token-cookbook)   | Approve or revoke delegates for compressed token accounts          |
  </Step>

  <Step>
    ### Advanced Guides

    | Guide                                                                    | Description                                                                                                       |
    | ------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------- |
    | [Create an Airdrop without Claim](/compressed-tokens/token-distribution) | ZK Compression is the most efficient way to distribute SPL tokens. Distribute via Webapp or customize with claim. |
    | [Privy Guide](/compressed-tokens/privy)                                  | Integrate compressed tokens with Privy embedded wallets for rent-free token accounts                              |
  </Step>
</Steps>
