> ## 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.

# Mint Compressed Tokens

> Mint tokens to compressed token accounts for recipients and increases a mint's token supply. Only the mint authority can perform this operation. 

```typescript theme={null}
// Mint compressed tokens - mints SPL tokens to pool, creates compressed token accounts
const transactionSignature = await mintTo(
    rpc,
    payer,
    mint, // SPL mint with interface PDA for compression
    recipient, // recipient address (toPubkey parameter)
    payer, // mint authority
    amount,
);
```

## Get Started

<Steps>
  <Step>
    ### Mint Compressed Tokens

    <Accordion title="Installation">
      <Tabs>
        <Tab title="npm">
          Install packages in your working directory:

          ```bash theme={null}
          npm install @lightprotocol/stateless.js@^0.23.0 \
                      @lightprotocol/compressed-token@^0.23.0
          ```

          Install the CLI globally:

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

        <Tab title="yarn">
          Install packages in your working directory:

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

          Install the CLI globally:

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

        <Tab title="pnpm">
          Install packages in your working directory:

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

          Install the CLI globally:

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

        <Tab title="SDK 2.0 (token-interface)">
          Install packages in your working directory:

          ```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
          ```

          Install the CLI globally:

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

    <Tabs>
      <Tab title="Localnet">
        ```bash theme={null}
        # start local test-validator in a separate terminal
        light test-validator
        ```

        <Note>
          In the code examples, use `createRpc()` without arguments for localnet.
        </Note>
      </Tab>

      <Tab title="Devnet">
        Get an API key from [Helius](https://helius.dev) and add to `.env`:

        ```bash title=".env" theme={null}
        API_KEY=<your-helius-api-key>
        ```

        <Note>
          In the code examples, use `createRpc(RPC_URL)` with the devnet URL.
        </Note>
      </Tab>
    </Tabs>

    <Tabs>
      <Tab title="Action">
        ```typescript theme={null}
        import "dotenv/config";
        import { Keypair } from "@solana/web3.js";
        import { createRpc } from "@lightprotocol/stateless.js";
        import { createMint, mintTo } from "@lightprotocol/compressed-token";
        import { homedir } from "os";
        import { readFileSync } from "fs";

        // devnet:
        const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`;
        // localnet:
        // const RPC_URL = undefined;
        const payer = Keypair.fromSecretKey(
            new Uint8Array(
                JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8"))
            )
        );

        (async function () {
            // devnet:
            const rpc = createRpc(RPC_URL);
            // localnet:
            // const rpc = createRpc();

            // Setup: Create mint
            const { mint } = await createMint(rpc, payer, payer.publicKey, 9);

            // Mint compressed tokens
            const recipient = Keypair.generate();
            const tx = await mintTo(rpc, payer, mint, recipient.publicKey, payer, 1_000_000_000);

            console.log("Mint:", mint.toBase58());
            console.log("Recipient:", recipient.publicKey.toBase58());
            console.log("Tx:", tx);
        })();
        ```
      </Tab>

      <Tab title="Instruction">
        ```typescript theme={null}
        import "dotenv/config";
        import { Keypair, ComputeBudgetProgram, Transaction, sendAndConfirmTransaction } from "@solana/web3.js";
        import { createRpc, bn, DerivationMode } from "@lightprotocol/stateless.js";
        import {
            createMintInterface,
            createAtaInterface,
            createMintToInterfaceInstruction,
            getMintInterface,
            getAssociatedTokenAddressInterface,
        } from "@lightprotocol/compressed-token";
        import { homedir } from "os";
        import { readFileSync } from "fs";

        // devnet:
        const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`;
        const rpc = createRpc(RPC_URL);
        // localnet:
        // const rpc = createRpc();

        const payer = Keypair.fromSecretKey(
            new Uint8Array(
                JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8"))
            )
        );

        (async function () {
            const { mint } = await createMintInterface(rpc, payer, payer, null, 9);

            const recipient = Keypair.generate();
            await createAtaInterface(rpc, payer, mint, recipient.publicKey);
            const destination = getAssociatedTokenAddressInterface(mint, recipient.publicKey);

            const mintInterface = await getMintInterface(rpc, mint);

            let validityProof;
            if (mintInterface.merkleContext) {
                validityProof = await rpc.getValidityProofV2(
                    [
                        {
                            hash: bn(mintInterface.merkleContext.hash),
                            leafIndex: mintInterface.merkleContext.leafIndex,
                            treeInfo: mintInterface.merkleContext.treeInfo,
                            proveByIndex: mintInterface.merkleContext.proveByIndex,
                        },
                    ],
                    [],
                    DerivationMode.compressible
                );
            }

            const ix = createMintToInterfaceInstruction(
                mintInterface,
                destination,
                payer.publicKey,
                payer.publicKey,
                1_000_000_000,
                validityProof
            );

            const tx = new Transaction().add(
                ComputeBudgetProgram.setComputeUnitLimit({ units: 500_000 }),
                ix
            );
            const signature = await sendAndConfirmTransaction(rpc, tx, [payer]);

            console.log("Mint:", mint.toBase58());
            console.log("Tx:", signature);
        })();
        ```
      </Tab>
    </Tabs>

    <Info>
      The SPL mint must have an SPL Interface PDA for compression.<br /> The script creates it for you.

      For development, create a new mint with SPL interface via [`createMint()`](https://github.com/Lightprotocol/examples-zk-compression/tree/main/compressed-token-cookbook) or add an SPL interface to an existing mint via [`createSplInterface()`](https://github.com/Lightprotocol/examples-zk-compression/tree/main/compressed-token-cookbook).
    </Info>
  </Step>
</Steps>

# Troubleshooting

<AccordionGroup>
  <Accordion title="TokenPool not found">
    ```typescript theme={null}
    // Error message: "TokenPool not found. Please create a compressed token
    // pool for mint: [ADDRESS] via createTokenPool().
    ```

    The mint does not have an interface PDA for compression. Ensure you created the mint using `createMint`.

    ```typescript theme={null}
    // Create mint with interface PDA for compression
    import { createMint } from '@lightprotocol/compressed-token';
    const { mint } = await createMint(rpc, payer, payer.publicKey, 9);
    ```
  </Accordion>

  <Accordion title="TokenPool mint does not match the provided mint">
    The interface PDA info doesn't correspond to the mint address. Ensure you're fetching the correct PDA:

    ```typescript theme={null}
    // Get the correct interface PDA for your mint
    const tokenPoolInfo = await getTokenPoolInfos(rpc, mint);
    ```
  </Accordion>

  <Accordion title="Amount and toPubkey arrays must have the same length">
    When minting to multiple recipients, ensure arrays are the same size.

    ```typescript theme={null}
    // Wrong: Mismatched array lengths
    const recipients = [addr1, addr2, addr3];
    const amounts = [100, 200]; // Only 2 amounts for 3 recipients

    // Correct: Same length arrays
    const recipients = [addr1, addr2, addr3];
    const amounts = [100, 200, 300]; // 3 amounts for 3 recipients
    ```
  </Accordion>
</AccordionGroup>

# Advanced Configuration

<AccordionGroup>
  <Accordion title="Mint to Multiple Recipients">
    ```typescript theme={null}
    // Mint different amounts to multiple recipients
    const recipients = [
        Keypair.generate().publicKey,
        Keypair.generate().publicKey,
        Keypair.generate().publicKey,
    ];

    const amounts = [
        1_000_000_000, // 1 token
        2_000_000_000, // 2 tokens
        500_000_000,   // 0.5 tokens
    ];

    const transactionSignature = await mintTo(
        rpc,
        payer,
        mint, // SPL mint with interface PDA for compression
        recipients, // array of recipients (toPubkey parameter)
        payer, // mint authority
        amounts, // array of amounts (amount parameter)
    );
    ```
  </Accordion>

  <Accordion title="With Custom Mint Authority">
    Mint tokens using a custom mint authority with `approveAndMintTo()`:

    ```typescript theme={null}
    import { approveAndMintTo } from '@lightprotocol/compressed-token';

    // Mint tokens with a separate mint authority
    const transactionSignature = await approveAndMintTo(
        rpc,
        payer,
        mint, // SPL mint with interface PDA for compression
        recipient.publicKey, // recipient of minted tokens (toPubkey parameter)
        mintAuthority, // mint authority
        mintAmount,
    );
    ```
  </Accordion>
</AccordionGroup>

# Next Steps

<Card title="How to Transfer Compressed Tokens" icon="chevron-right" color="#0066ff" href="/compressed-tokens/guides/transfer-compressed-tokens" horizontal />
