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

# Combine Instructions in One Transaction

> Guide to combine multiple instructions in a single transaction. Full code example for interface PDA creation and for first-time compression of existing SPL tokens.

The SDK provides instruction-level APIs that return instructions without sending transactions. Combine these instructions to build custom transactions with multiple instructions.

<Note>
  This guide demonstrates creating an interface PDA and compressing existing SPL tokens in a single transaction.
</Note>

# Full Code Example

<Steps>
  <Step>
    ### Prerequisites

    Make sure you have dependencies and developer environment set up!

    <Accordion title="Prerequisites & Setup">
      **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>

      **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>
    </Accordion>
  </Step>

  <Step>
    ### Create Interface PDA + Compress

    ```typescript create-pool-and-compress.ts highlight={26,71} expandable theme={null}
    // 1. Setup: Create regular SPL token and mint to ATA
    // 2. Build instructions for create interface PDA and compress
    // 3. Combine instructions in one transaction
    // 4. Verify compressed balance

    import {
        Keypair,
        ComputeBudgetProgram,
    } from '@solana/web3.js';
    import {
        createRpc,
        buildAndSignTx,
        sendAndConfirmTx,
        selectStateTreeInfo,
    } from '@lightprotocol/stateless.js';
    import { CompressedTokenProgram } from '@lightprotocol/compressed-token';
    import {
        createMint,
        getOrCreateAssociatedTokenAccount,
        mintTo,
        TOKEN_PROGRAM_ID,
    } from '@solana/spl-token';
    import BN from 'bn.js';

    async function createPoolAndCompress() {
        // Step 1: Setup - Create regular SPL token and mint to ATA
        const rpc = createRpc();
        const payer = Keypair.generate();
        const airdropSignature = await rpc.requestAirdrop(payer.publicKey, 1000000000);
        await rpc.confirmTransaction(airdropSignature);

        // Create regular SPL token mint
        const mint = await createMint(
            rpc,
            payer,
            payer.publicKey,
            null,
            9,
            undefined,
            undefined,
            TOKEN_PROGRAM_ID
        );

        // Create ATA and mint tokens to it
        const ata = await getOrCreateAssociatedTokenAccount(
            rpc,
            payer,
            mint,
            payer.publicKey,
            undefined,
            undefined,
            undefined,
            TOKEN_PROGRAM_ID
        );

        await mintTo(
            rpc,
            payer,
            mint,
            ata.address,
            payer,
            1_000_000_000, // 1 token with 9 decimals
            undefined,
            undefined,
            TOKEN_PROGRAM_ID
        );

        console.log("Regular SPL token created:", mint.toBase58());
        console.log("ATA balance:", 1, "token");

        // Step 2: Build instructions for create interface PDA and compress
        const outputStateTreeInfo = selectStateTreeInfo(await rpc.getStateTreeInfos());

        // Derive interface PDA
        const tokenPoolPda = CompressedTokenProgram.deriveTokenPoolPda(mint);

        // Create interface PDA instruction
        const createTokenPoolIx = await CompressedTokenProgram.createTokenPool({
            feePayer: payer.publicKey,
            mint,
            tokenProgram: TOKEN_PROGRAM_ID,
        });

        // Manually construct TokenPoolInfo for first-time compression
        const tokenPoolInfo = {
            mint: mint,
            tokenPoolPda: tokenPoolPda,
            tokenProgram: TOKEN_PROGRAM_ID,
            isInitialized: true, // Set to true even though pool will be created in this tx
            balance: new BN(0),
            poolIndex: 0,
            bump: 0, // Placeholder value
        };

        // Create compress instruction
        const compressIx = await CompressedTokenProgram.compress({
            outputStateTreeInfo,
            tokenPoolInfo,
            payer: payer.publicKey,
            owner: payer.publicKey,
            source: ata.address,
            toAddress: payer.publicKey,
            amount: new BN(1_000_000_000),
            mint,
        });

        // Step 3: Combine instructions in one transaction
        const { blockhash } = await rpc.getLatestBlockhash();

        const allInstructions = [
            ComputeBudgetProgram.setComputeUnitLimit({ units: 1_000_000 }),
            createTokenPoolIx,
            compressIx,
        ];

        const tx = buildAndSignTx(
            allInstructions,
            payer,
            blockhash,
            []
        );

        const txId = await sendAndConfirmTx(rpc, tx);

        console.log("Interface PDA created and tokens compressed");
        console.log("Transaction:", txId);

        // Step 4: Verify compressed balance
        const compressedAccounts = await rpc.getCompressedTokenAccountsByOwner(
            payer.publicKey,
            { mint }
        );

        const compressedBalance = compressedAccounts.items.reduce(
            (sum, account) => sum.add(account.parsed.amount),
            new BN(0)
        );

        console.log("Compressed balance:", compressedBalance.toNumber() / 1_000_000_000, "tokens");

        return {
            transactionSignature: txId,
            mint,
            compressedBalance: compressedBalance.toNumber(),
        };
    }

    createPoolAndCompress().catch(console.error);
    ```
  </Step>
</Steps>

# Next Steps

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