> ## Documentation Index
> Fetch the complete documentation index at: https://luminouslabs-cc5545c6-swen-add-code-runner.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Wrap & Unwrap SPL/T22 <> Light Token Accounts

> Convert between SPL/T22 token and light-token accounts. Used for on/off-ramp to centralized exchanges that only support SPL.

***

* **Wrap**: Move tokens from SPL/T22 account → light-token ATA (hot balance)
* **Unwrap**: Move tokens from light-token ATA (hot balance) → SPL/T22 account

<Info>
  Find the source code:
  [wrap.ts](https://github.com/Lightprotocol/light-protocol/blob/0c4e2417b2df2d564721b89e18d1aad3665120e7/js/compressed-token/src/v3/actions/wrap.ts)
  |
  [unwrap.ts](https://github.com/Lightprotocol/light-protocol/blob/0c4e2417b2df2d564721b89e18d1aad3665120e7/js/compressed-token/src/v3/actions/unwrap.ts)
</Info>

## Get Started

<Tabs>
  <Tab title="Wrap">
    <Steps>
      <Step>
        ### Wrap SPL Tokens to Light Token ATA

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

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

              Install the CLI globally:

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

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

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

              Install the CLI globally:

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

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

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

              Install the CLI globally:

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

        ```bash theme={null}
        # Start local test-validator in separate terminal
        light test-validator
        ```

        <CodeGroup>
          ```typescript Action theme={null}
          import { Keypair } from "@solana/web3.js";
          import { createRpc, bn } from "@lightprotocol/stateless.js";
          import {
            createMint,
            mintTo,
            decompress,
            wrap,
            getAssociatedTokenAddressInterface,
            createAtaInterfaceIdempotent,
          } from "@lightprotocol/compressed-token";
          import { createAssociatedTokenAccount } from "@solana/spl-token";

          async function main() {
          const rpc = createRpc();
          const payer = Keypair.generate();
          const sig = await rpc.requestAirdrop(payer.publicKey, 10e9);
          await rpc.confirmTransaction(sig);

          // Setup: Get SPL tokens (needed to wrap)
          const { mint } = await createMint(rpc, payer, payer.publicKey, 9);
          const splAta = await createAssociatedTokenAccount(rpc, payer, mint, payer.publicKey);
          await mintTo(rpc, payer, mint, payer.publicKey, payer, bn(1000));
          await decompress(rpc, payer, mint, bn(1000), payer, splAta);

          // Wrap SPL tokens to rent-free token ATA
          const ctokenAta = getAssociatedTokenAddressInterface(mint, payer.publicKey);
          await createAtaInterfaceIdempotent(rpc, payer, mint, payer.publicKey);

          const tx = await wrap(rpc, payer, splAta, ctokenAta, payer, mint, bn(500));

          console.log("Tx:", tx);
          }

          main().catch(console.error);

          ```

          ```typescript Instruction theme={null}
          import { Keypair, ComputeBudgetProgram } from "@solana/web3.js";
          import {
            createRpc,
            buildAndSignTx,
            sendAndConfirmTx,
            dedupeSigner,
            bn,
          } from "@lightprotocol/stateless.js";
          import {
            createMint,
            mintTo,
            decompress,
            createWrapInstruction,
            getAssociatedTokenAddressInterface,
            createAtaInterfaceIdempotent,
            getSplInterfaceInfos,
          } from "@lightprotocol/compressed-token";
          import { createAssociatedTokenAccount } from "@solana/spl-token";

          async function main() {
            const rpc = createRpc();
            const payer = Keypair.generate();
            await rpc.requestAirdrop(payer.publicKey, 10e9);

            const owner = Keypair.generate();
            await rpc.requestAirdrop(owner.publicKey, 1e9);

            const mintAuthority = Keypair.generate();
            const mintKeypair = Keypair.generate();
            const { mint } = await createMint(
              rpc,
              payer,
              mintAuthority.publicKey,
              9,
              mintKeypair
            );

            const splAta = await createAssociatedTokenAccount(
              rpc,
              payer,
              mint,
              owner.publicKey
            );

            await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(1000));
            await decompress(rpc, payer, mint, bn(1000), owner, splAta);

            // Create c-token ATA (destination)
            const ctokenAta = getAssociatedTokenAddressInterface(mint, owner.publicKey);
            await createAtaInterfaceIdempotent(rpc, payer, mint, owner.publicKey);

            // Get SPL interface info for the mint
            const splInterfaceInfos = await getSplInterfaceInfos(rpc, mint);
            const splInterfaceInfo = splInterfaceInfos.find((info) => info.isInitialized);

            if (!splInterfaceInfo) {
              throw new Error("No SPL interface found");
            }

            // Create wrap instruction
            const ix = createWrapInstruction(
              splAta,
              ctokenAta,
              owner.publicKey,
              mint,
              bn(500),
              splInterfaceInfo,
              payer.publicKey
            );

            // Build, sign, and send transaction
            const { blockhash } = await rpc.getLatestBlockhash();
            const additionalSigners = dedupeSigner(payer, [owner]);

            const tx = buildAndSignTx(
              [ComputeBudgetProgram.setComputeUnitLimit({ units: 200_000 }), ix],
              payer,
              blockhash,
              additionalSigners
            );

            const signature = await sendAndConfirmTx(rpc, tx);
            console.log("Wrapped 500 tokens to c-token ATA");
            console.log("Transaction:", signature);
          }

          main().catch(console.error);
          ```
        </CodeGroup>
      </Step>
    </Steps>
  </Tab>

  <Tab title="Unwrap">
    <Steps>
      <Step>
        ### Unwrap Light Tokens to SPL Account

        <CodeGroup>
          ```typescript Action theme={null}
          import { Keypair } from "@solana/web3.js";
          import { createRpc, bn } from "@lightprotocol/stateless.js";
          import { createMint, mintTo } from "@lightprotocol/compressed-token";
          import { unwrap } from "@lightprotocol/compressed-token/unified";
          import { createAssociatedTokenAccount } from "@solana/spl-token";

          async function main() {
          const rpc = createRpc();
          const payer = Keypair.generate();
          const sig = await rpc.requestAirdrop(payer.publicKey, 10e9);
          await rpc.confirmTransaction(sig);

          // Setup: Get compressed tokens (cold storage)
          const { mint } = await createMint(rpc, payer, payer.publicKey, 9);
          await mintTo(rpc, payer, mint, payer.publicKey, payer, bn(1000));

          // Unwrap rent-free tokens to SPL ATA
          const splAta = await createAssociatedTokenAccount(rpc, payer, mint, payer.publicKey);
          const tx = await unwrap(rpc, payer, splAta, payer, mint, bn(500));

          console.log("Tx:", tx);
          }

          main().catch(console.error);

          ```

          ```typescript Instruction theme={null}
          import { Keypair, ComputeBudgetProgram } from "@solana/web3.js";
          import {
            createRpc,
            buildAndSignTx,
            sendAndConfirmTx,
            dedupeSigner,
            bn,
          } from "@lightprotocol/stateless.js";
          import {
            createMint,
            mintTo,
            loadAta,
            getAssociatedTokenAddressInterface,
            getSplInterfaceInfos,
          } from "@lightprotocol/compressed-token";
          import { createUnwrapInstruction } from "@lightprotocol/compressed-token/unified";
          import { createAssociatedTokenAccount } from "@solana/spl-token";

          async function main() {
            const rpc = createRpc();
            const payer = Keypair.generate();
            await rpc.requestAirdrop(payer.publicKey, 10e9);

            const owner = Keypair.generate();
            await rpc.requestAirdrop(owner.publicKey, 1e9);

            const mintAuthority = Keypair.generate();
            const mintKeypair = Keypair.generate();
            const { mint } = await createMint(
              rpc,
              payer,
              mintAuthority.publicKey,
              9,
              mintKeypair
            );

            // Mint compressed tokens to owner
            await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(1000));

            // Load compressed tokens to c-token ATA (hot balance)
            const ctokenAta = getAssociatedTokenAddressInterface(mint, owner.publicKey);
            await loadAta(rpc, ctokenAta, owner, mint, payer);

            // Create destination SPL ATA
            const splAta = await createAssociatedTokenAccount(
              rpc,
              payer,
              mint,
              owner.publicKey
            );

            // Get SPL interface info for the mint
            const splInterfaceInfos = await getSplInterfaceInfos(rpc, mint);
            const splInterfaceInfo = splInterfaceInfos.find((info) => info.isInitialized);

            if (!splInterfaceInfo) {
              throw new Error("No SPL interface found");
            }

            // Create unwrap instruction
            const ix = createUnwrapInstruction(
              ctokenAta,
              splAta,
              owner.publicKey,
              mint,
              bn(500),
              splInterfaceInfo,
              payer.publicKey
            );

            // Build, sign, and send transaction
            const { blockhash } = await rpc.getLatestBlockhash();
            const additionalSigners = dedupeSigner(payer, [owner]);

            const tx = buildAndSignTx(
              [ComputeBudgetProgram.setComputeUnitLimit({ units: 200_000 }), ix],
              payer,
              blockhash,
              additionalSigners
            );

            const signature = await sendAndConfirmTx(rpc, tx);
            console.log("Unwrapped 500 tokens to SPL ATA");
            console.log("Transaction:", signature);
          }

          main().catch(console.error);
          ```
        </CodeGroup>
      </Step>
    </Steps>
  </Tab>
</Tabs>
