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

# Wrap and Unwrap

> Move tokens between SPL / Token 2022 and Light Token accounts. Use wrap/unwrap to interoperate with applications that only support SPL or Token 2022.

<Accordion title="Agent skill">
  Use the [payments](https://github.com/Lightprotocol/skills/tree/main/skills/payments) agent skill to add light-token payment support to your project:

  ```
  npx skills add Lightprotocol/skills
  ```

  For orchestration, install the [general skill](https://zkcompression.com/skill.md):

  ```bash theme={null}
  npx skills add https://zkcompression.com
  ```
</Accordion>

<Tabs>
  <Tab title="Guide">
    ## Setup

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

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

    const rpc = createRpc(RPC_ENDPOINT);
    ```

    ## Wrap from SPL

    <Note>
      Find a full code example [here](https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/interop/wrap.ts).
    </Note>

    <Tabs>
      <Tab title="Instruction">
        ```typescript theme={null}
        import { Transaction } from "@solana/web3.js";
        import { getAssociatedTokenAddressSync } from "@solana/spl-token";
        import {
          createWrapInstruction,
          getAssociatedTokenAddressInterface,
        } from "@lightprotocol/compressed-token/unified";
        import { getSplInterfaceInfos } from "@lightprotocol/compressed-token";

        const splAta = getAssociatedTokenAddressSync(mint, owner.publicKey);
        const tokenAta = getAssociatedTokenAddressInterface(mint, owner.publicKey);

        const splInterfaceInfos = await getSplInterfaceInfos(rpc, mint);
        const splInterfaceInfo = splInterfaceInfos.find((i) => i.isInitialized);

        const tx = new Transaction().add(
          createWrapInstruction(
            splAta,
            tokenAta,
            owner.publicKey,
            mint,
            amount,
            splInterfaceInfo,
            decimals,
            payer.publicKey
          )
        );
        ```
      </Tab>

      <Tab title="SDK 2.0 (token-interface)">
        ```typescript theme={null}
        import { ComputeBudgetProgram, Keypair, Transaction, sendAndConfirmTransaction } from "@solana/web3.js";
        import { createRpc } from "@lightprotocol/stateless.js";
        import {
          createAtaInstruction,
          createWrapInstruction,
          getAtaAddress,
          getSplInterfaces,
        } from "@lightprotocol/token-interface";

        const rpc = createRpc();
        const payer = Keypair.fromSecretKey(/* ... */);

        const mint = /* existing SPL/Token-2022 mint */;
        const splAta = /* existing SPL ATA */;
        const lightTokenAta = getAtaAddress({ mint, owner: payer.publicKey });

        const createAtaIx = createAtaInstruction({
          payer: payer.publicKey,
          owner: payer.publicKey,
          mint,
        });

        const splInterfaces = await getSplInterfaces(rpc, mint);
        const splInterface =
          splInterfaces.find((info) => info.isInitialized) ?? splInterfaces[0];
        if (!splInterface) throw new Error("No SPL interface found");

        const wrapIx = createWrapInstruction({
          source: splAta,
          destination: lightTokenAta,
          owner: payer.publicKey,
          mint,
          amount: 500n,
          splInterface,
          decimals: 9,
          payer: payer.publicKey,
        });

        const tx = new Transaction().add(
          ComputeBudgetProgram.setComputeUnitLimit({ units: 200_000 }),
          createAtaIx,
          wrapIx
        );
        const signature = await sendAndConfirmTransaction(rpc, tx, [payer]);
        console.log("Tx:", signature);
        ```
      </Tab>

      <Tab title="Action">
        ```typescript theme={null}
        import { getAssociatedTokenAddressSync } from "@solana/spl-token";
        import {
          wrap,
          getAssociatedTokenAddressInterface,
        } from "@lightprotocol/compressed-token/unified";

        const splAta = getAssociatedTokenAddressSync(mint, owner.publicKey);
        const tokenAta = getAssociatedTokenAddressInterface(mint, owner.publicKey);

        await wrap(rpc, payer, splAta, tokenAta, owner, mint, amount);
        ```
      </Tab>
    </Tabs>

    ## Unwrap to SPL

    <Note>
      Find a full code example [here](https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/interop/unwrap.ts).
    </Note>

    Unwrap moves the token balance from a Light Token associated token account to an SPL associated token account.
    Use this to compose with applications that do not yet support Light Token.

    <Tabs>
      <Tab title="Instruction">
        ```typescript theme={null}
        import { Transaction, sendAndConfirmTransaction } from "@solana/web3.js";
        import { getAssociatedTokenAddressSync } from "@solana/spl-token";
        import { createUnwrapInstructions } from "@lightprotocol/compressed-token/unified";

        const splAta = getAssociatedTokenAddressSync(mint, owner.publicKey);

        // Each inner array = one transaction. Handles loading + unwrapping together.
        const instructions = await createUnwrapInstructions(
          rpc,
          splAta,
          owner.publicKey,
          mint,
          amount,
          payer.publicKey
        );

        for (const ixs of instructions) {
          const tx = new Transaction().add(...ixs);
          await sendAndConfirmTransaction(rpc, tx, [payer, owner]);
        }
        ```
      </Tab>

      <Tab title="SDK 2.0 (token-interface)">
        ```typescript theme={null}
        import { Keypair, Transaction, sendAndConfirmTransaction } from "@solana/web3.js";
        import { createRpc } from "@lightprotocol/stateless.js";
        import { createUnwrapInstruction, getSplInterfaces } from "@lightprotocol/token-interface";

        const rpc = createRpc();
        const payer = Keypair.fromSecretKey(/* ... */);

        const mint = /* existing SPL/Token-2022 mint */;
        const lightTokenAta = /* existing Light ATA */;
        const splAta = /* destination SPL ATA */;

        const splInterfaces = await getSplInterfaces(rpc, mint);
        const splInterface =
          splInterfaces.find((info) => info.isInitialized) ?? splInterfaces[0];
        if (!splInterface) throw new Error("No SPL interface found");

        const unwrapIx = createUnwrapInstruction({
          source: lightTokenAta,
          destination: splAta,
          owner: payer.publicKey,
          mint,
          amount: 500n,
          splInterface,
          decimals: 9,
          payer: payer.publicKey,
        });

        const tx = new Transaction().add(unwrapIx);
        const signature = await sendAndConfirmTransaction(rpc, tx, [payer]);
        console.log("Tx:", signature);
        ```
      </Tab>

      <Tab title="Action">
        ```typescript theme={null}
        import { getAssociatedTokenAddressSync } from "@solana/spl-token";
        import { unwrap } from "@lightprotocol/compressed-token/unified";

        const splAta = getAssociatedTokenAddressSync(mint, owner.publicKey);

        await unwrap(rpc, payer, splAta, owner, mint, amount);
        ```
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="AI Prompt">
    <Prompt description="Integrate light-token APIs for stablecoin payments" actions={["copy", "cursor"]}>
      {`---
            description: Integrate light-token APIs for stablecoin payments
            allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression
            ---

            ## Integrate light-token APIs for stablecoin payments

            Context:
            - Guide: https://zkcompression.com/light-token/payments/overview
            - 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
            - Packages: @lightprotocol/compressed-token, @lightprotocol/stateless.js
            - Import from @lightprotocol/compressed-token/unified for all interface APIs

            SPL → Light Token API mapping:
            | Operation    | SPL                               | Light Token                              |
            | Receive      | getOrCreateAssociatedTokenAccount() | createLoadAtaInstructions() / loadAta()  |
            | Transfer     | createTransferInstruction()        | createTransferInterfaceInstructions()    |
            | Delegated Transfer | transfer() (delegate signs)  | transferInterface(..., ownerPubkey, delegateSigner, ...) |
            | Get Balance  | getAccount()                      | getAtaInterface()                        |
            | Tx History   | getSignaturesForAddress()         | getSignaturesForOwnerInterface()         |
            | Wrap SPL     | N/A                               | createWrapInstruction() / wrap()         |
            | Unwrap       | N/A                               | createUnwrapInstructions() / unwrap()    |

            ### 1. Index project
            - Grep \`@solana/spl-token|@lightprotocol|createTransferInstruction|getAccount|Connection|Keypair|stablecoin|payment\` across src/
            - Glob \`**/*.ts\` and \`**/*.tsx\` for project structure
            - Identify: RPC setup, existing token operations, payment flow, wallet signing pattern
            - Check package.json for existing @lightprotocol/* or @solana/spl-token dependencies
            - Task subagent (Grep/Read/WebFetch) if project has multiple packages to scan in parallel

            ### 2. Read references
            - WebFetch the guide above — review Instruction and Action tabs for each operation
            - 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? (new payment integration, migrate existing SPL payment flow, add alongside existing SPL)
            - AskUserQuestion: which operations? (receive, send, balance, history, wrap, unwrap — or all)
            - AskUserQuestion: instruction-level API (build your own transactions) or action-level API (high-level, fewer lines)?
            - 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
            - Verify existing connection/signer setup is compatible (createRpc with ZK Compression endpoint)
            - Key pattern: import from \`@lightprotocol/compressed-token/unified\` for all interface APIs
            - 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/unified\` for the interface APIs
            - 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

            ### Resources

            Guides:
            - Basic payment: https://zkcompression.com/light-token/payments/basic-payment
            - Batch payments: https://zkcompression.com/light-token/payments/batch-payments
            - Payment with memo: https://zkcompression.com/light-token/payments/payment-with-memo
            - Receive payments: https://zkcompression.com/light-token/payments/receive-payments
            - Verify payments: https://zkcompression.com/light-token/payments/verify-payments
            - Verify recipient address: https://zkcompression.com/light-token/payments/verify-recipient-address
            - Spend permissions: https://zkcompression.com/light-token/payments/spend-permissions
            - Wrap and unwrap: https://zkcompression.com/light-token/payments/wrap-unwrap
            - Production readiness: https://zkcompression.com/light-token/payments/production-readiness
            - FAQ: https://zkcompression.com/faq
            - Sign with Privy: https://zkcompression.com/light-token/wallets/privy
            - Sign with Wallet Adapter: https://zkcompression.com/light-token/wallets/wallet-adapter
            - Gasless transactions: https://zkcompression.com/light-token/wallets/gasless-transactions

            Examples:
            - All payments: https://github.com/Lightprotocol/examples-light-token/tree/main/toolkits/payments
            - Send (instruction): https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/send/basic-send-instruction.ts
            - Send (action): https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/send/basic-send-action.ts
            - Batch send: https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/send/batch-send.ts
            - Payment with memo: https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/send/payment-with-memo.ts
            - Receive: https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/receive/receive.ts
            - Get balance: https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/verify/get-balance.ts
            - Get history: https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/verify/get-history.ts
            - Verify address: https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/verify/verify-address.ts
            - Wrap: https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/interop/wrap.ts
            - Unwrap: https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/interop/unwrap.ts
            - Privy (Node.js): https://github.com/Lightprotocol/examples-light-token/tree/main/toolkits/sign-with-privy/nodejs
            - Privy (React): https://github.com/Lightprotocol/examples-light-token/tree/main/toolkits/sign-with-privy/react
            - Wallet Adapter (React): https://github.com/Lightprotocol/examples-light-token/tree/main/toolkits/sign-with-wallet-adapter/react
            - Gasless transfer: https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/gasless-transactions/typescript/gasless-transfer.ts`}
    </Prompt>

    ```text theme={null}
    ---
    description: Integrate light-token APIs for stablecoin payments
    allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression
    ---

    ## Integrate light-token APIs for stablecoin payments

    Context:
    - Guide: https://zkcompression.com/light-token/payments/overview
    - 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
    - Packages: @lightprotocol/compressed-token, @lightprotocol/stateless.js
    - Import from @lightprotocol/compressed-token/unified for all interface APIs

    SPL → Light Token API mapping:
    | Operation    | SPL                               | Light Token                              |
    | Receive      | getOrCreateAssociatedTokenAccount() | createLoadAtaInstructions() / loadAta()  |
    | Transfer     | createTransferInstruction()        | createTransferInterfaceInstructions()    |
    | Delegated Transfer | transfer() (delegate signs)  | transferInterface(..., ownerPubkey, delegateSigner, ...) |
    | Get Balance  | getAccount()                      | getAtaInterface()                        |
    | Tx History   | getSignaturesForAddress()         | getSignaturesForOwnerInterface()         |
    | Wrap SPL     | N/A                               | createWrapInstruction() / wrap()         |
    | Unwrap       | N/A                               | createUnwrapInstructions() / unwrap()    |

    ### 1. Index project
    - Grep `@solana/spl-token|@lightprotocol|createTransferInstruction|getAccount|Connection|Keypair|stablecoin|payment` across src/
    - Glob `**/*.ts` and `**/*.tsx` for project structure
    - Identify: RPC setup, existing token operations, payment flow, wallet signing pattern
    - Check package.json for existing @lightprotocol/* or @solana/spl-token dependencies
    - Task subagent (Grep/Read/WebFetch) if project has multiple packages to scan in parallel

    ### 2. Read references
    - WebFetch the guide above — review Instruction and Action tabs for each operation
    - 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? (new payment integration, migrate existing SPL payment flow, add alongside existing SPL)
    - AskUserQuestion: which operations? (receive, send, balance, history, wrap, unwrap — or all)
    - AskUserQuestion: instruction-level API (build your own transactions) or action-level API (high-level, fewer lines)?
    - 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
    - Verify existing connection/signer setup is compatible (createRpc with ZK Compression endpoint)
    - Key pattern: import from `@lightprotocol/compressed-token/unified` for all interface APIs
    - 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/unified` for the interface APIs
    - 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

    ### Resources

    Guides:
    - Basic payment: https://zkcompression.com/light-token/payments/basic-payment
    - Batch payments: https://zkcompression.com/light-token/payments/batch-payments
    - Payment with memo: https://zkcompression.com/light-token/payments/payment-with-memo
    - Receive payments: https://zkcompression.com/light-token/payments/receive-payments
    - Verify payments: https://zkcompression.com/light-token/payments/verify-payments
    - Verify recipient address: https://zkcompression.com/light-token/payments/verify-recipient-address
    - Spend permissions: https://zkcompression.com/light-token/payments/spend-permissions
    - Wrap and unwrap: https://zkcompression.com/light-token/payments/wrap-unwrap
    - Production readiness: https://zkcompression.com/light-token/payments/production-readiness
    - FAQ: https://zkcompression.com/faq
    - Sign with Privy: https://zkcompression.com/light-token/wallets/privy
    - Sign with Wallet Adapter: https://zkcompression.com/light-token/wallets/wallet-adapter
    - Gasless transactions: https://zkcompression.com/light-token/wallets/gasless-transactions

    Examples:
    - All payments: https://github.com/Lightprotocol/examples-light-token/tree/main/toolkits/payments
    - Send (instruction): https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/send/basic-send-instruction.ts
    - Send (action): https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/send/basic-send-action.ts
    - Batch send: https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/send/batch-send.ts
    - Payment with memo: https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/send/payment-with-memo.ts
    - Receive: https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/receive/receive.ts
    - Get balance: https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/verify/get-balance.ts
    - Get history: https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/verify/get-history.ts
    - Verify address: https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/verify/verify-address.ts
    - Wrap: https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/interop/wrap.ts
    - Unwrap: https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/interop/unwrap.ts
    - Privy (Node.js): https://github.com/Lightprotocol/examples-light-token/tree/main/toolkits/sign-with-privy/nodejs
    - Privy (React): https://github.com/Lightprotocol/examples-light-token/tree/main/toolkits/sign-with-privy/react
    - Wallet Adapter (React): https://github.com/Lightprotocol/examples-light-token/tree/main/toolkits/sign-with-wallet-adapter/react
    - Gasless transfer: https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/gasless-transactions/typescript/gasless-transfer.ts
    ```
  </Tab>
</Tabs>

## Related guides

<CardGroup cols={3}>
  <Card title="Basic payment" icon="arrow-right" href="/light-token/payments/basic-payment">
    Send a single token transfer.
  </Card>

  <Card title="Gasless transactions" icon="hand-holding-dollar" href="/light-token/wallets/gasless-transactions">
    Abstract SOL fees from the user.
  </Card>

  <Card title="Verify payments" icon="magnifying-glass" href="/light-token/payments/verify-payments">
    Query balances and transaction history.
  </Card>
</CardGroup>

***

## Didn't find what you were looking for?

<Callout type="info">
  Reach out! [Telegram](https://t.me/swen_light) | [email](mailto:support@lightprotocol.com) | [Discord](https://discord.com/invite/7cJ8BhAXhu)
</Callout>
