Skip to main content
  1. The light-token API matches the SPL-token API almost entirely, and extends their functionality to include the light token program in addition to the SPL-token and Token-2022 programs.
  2. Your users receive the same stablecoin, just stored more efficiently.
Creation CostSPLlight-token
Token Account~2,000,000 lamports~11,000 lamports

What you will implement

SPLLight
Get/Create ATAgetOrCreateAssociatedTokenAccount()getOrCreateAtaInterface()
Derive ATAgetAssociatedTokenAddress()getAssociatedTokenAddressInterface()
TransfertransferChecked()transferInterface()
Get BalancegetAccount()getAtaInterface()
Tx HistorygetSignaturesForAddress()rpc.getSignaturesForOwnerInterface()
Wrap from SPLN/Awrap()
Unwrap to SPLN/Aunwrap()
Find full code examples here.

Setup

npm install @lightprotocol/compressed-token@alpha \
            @lightprotocol/stateless.js@alpha
import { createRpc } from "@lightprotocol/stateless.js";

import {
  getOrCreateAtaInterface,
  getAtaInterface,
  getAssociatedTokenAddressInterface,
  transferInterface,
  wrap,
  unwrap,
} from "@lightprotocol/compressed-token/unified";

const rpc = createRpc(RPC_ENDPOINT);

Receive Payments

Find a full code example here.
import { Transaction } from "@solana/web3.js";
import {
  createAssociatedTokenAccountInterfaceIdempotentInstruction,
  createLoadAtaInstructions,
  getAssociatedTokenAddressInterface,
} from "@lightprotocol/compressed-token/unified";
import { CTOKEN_PROGRAM_ID } from "@lightprotocol/stateless.js";

const ata = getAssociatedTokenAddressInterface(mint, recipient);

const tx = new Transaction().add(
  createAssociatedTokenAccountInterfaceIdempotentInstruction(
    payer.publicKey,
    ata,
    recipient,
    mint,
    CTOKEN_PROGRAM_ID
  ),
  ...(await createLoadAtaInstructions(
    rpc,
    ata,
    recipient,
    mint,
    payer.publicKey
  ))
);
import {
  createAssociatedTokenAccountInstruction,
  getAssociatedTokenAddressSync,
} from "@solana/spl-token";

const ata = getAssociatedTokenAddressSync(mint, recipient);

const tx = new Transaction().add(
  createAssociatedTokenAccountInstruction(payer.publicKey, ata, recipient, mint)
);

Send Payments

Find a full code example here.
import { Transaction } from "@solana/web3.js";
import {
  createLoadAtaInstructions,
  createTransferInterfaceInstruction,
  getAssociatedTokenAddressInterface,
} from "@lightprotocol/compressed-token/unified";

const sourceAta = getAssociatedTokenAddressInterface(mint, owner.publicKey);
const destinationAta = getAssociatedTokenAddressInterface(mint, recipient);

const tx = new Transaction().add(
  ...(await createLoadAtaInstructions(
    rpc,
    sourceAta,
    owner.publicKey,
    mint,
    payer.publicKey
  )),
  createTransferInterfaceInstruction(
    sourceAta,
    destinationAta,
    owner.publicKey,
    amount
  )
);
To ensure your recipient’s ATA exists, prepend an idempotent creation instruction:
import { Transaction } from "@solana/web3.js";
import {
  createAssociatedTokenAccountInterfaceIdempotentInstruction,
  createLoadAtaInstructions,
  createTransferInterfaceInstruction,
  getAssociatedTokenAddressInterface,
} from "@lightprotocol/compressed-token/unified";
import { CTOKEN_PROGRAM_ID } from "@lightprotocol/stateless.js";

const sourceAta = getAssociatedTokenAddressInterface(mint, owner.publicKey);
const destinationAta = getAssociatedTokenAddressInterface(mint, recipient);

const tx = new Transaction().add(
  createAssociatedTokenAccountInterfaceIdempotentInstruction(
    payer.publicKey,
    destinationAta,
    recipient,
    mint,
    CTOKEN_PROGRAM_ID
  ),
  ...(await createLoadAtaInstructions(
    rpc,
    sourceAta,
    owner.publicKey,
    mint,
    payer.publicKey
  )),
  createTransferInterfaceInstruction(
    sourceAta,
    destinationAta,
    owner.publicKey,
    amount
  )
);
import {
  getAssociatedTokenAddressSync,
  createTransferInstruction,
} from "@solana/spl-token";

const sourceAta = getAssociatedTokenAddressSync(mint, owner.publicKey);
const destinationAta = getAssociatedTokenAddressSync(mint, recipient);

const tx = new Transaction().add(
  createTransferInstruction(sourceAta, destinationAta, owner.publicKey, amount)
);
With idempotent ATA creation:
import {
  getAssociatedTokenAddressSync,
  createAssociatedTokenAccountIdempotentInstruction,
  createTransferInstruction,
} from "@solana/spl-token";

const sourceAta = getAssociatedTokenAddressSync(mint, owner.publicKey);
const destinationAta = getAssociatedTokenAddressSync(mint, recipient);

const tx = new Transaction().add(
  createAssociatedTokenAccountIdempotentInstruction(
    payer.publicKey,
    destinationAta,
    recipient,
    mint
  ),
  createTransferInstruction(sourceAta, destinationAta, owner.publicKey, amount)
);

Show Balance

Find a full code example here.
import {
  getAssociatedTokenAddressInterface,
  getAtaInterface,
} from "@lightprotocol/compressed-token/unified";

const ata = getAssociatedTokenAddressInterface(mint, owner);
const account = await getAtaInterface(rpc, ata, owner, mint);

console.log(account.parsed.amount);
import { getAccount } from "@solana/spl-token";

const account = await getAccount(connection, ata);

console.log(account.amount);

Transaction History

Find a full code example here.
const result = await rpc.getSignaturesForOwnerInterface(owner);

console.log(result.signatures); // All signatures
Use getSignaturesForAddressInterface(address) if you want address-specific rather than owner-wide history.
const signatures = await connection.getSignaturesForAddress(ata);

Wrap from SPL

Wrap tokens from SPL/Token-2022 accounts to light-token ATA.
Find a full code example here.
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 ctokenAta = getAssociatedTokenAddressInterface(mint, owner.publicKey);

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

const tx = new Transaction().add(
  createWrapInstruction(
    splAta,
    ctokenAta,
    owner.publicKey,
    mint,
    amount,
    splInterfaceInfo
  )
);

Unwrap to SPL

You can compose with applications that do not yet support the light-token standard by unwrapping your tokens. Unwrap moves the token balance from a light-token account to a SPL-token account.
Find a full code example here.
import { Transaction } from "@solana/web3.js";
import { getAssociatedTokenAddressSync } from "@solana/spl-token";
import {
  createLoadAtaInstructions,
  createUnwrapInstruction,
  getAssociatedTokenAddressInterface,
} from "@lightprotocol/compressed-token/unified";
import { getSplInterfaceInfos } from "@lightprotocol/compressed-token";

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

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

const tx = new Transaction().add(
  ...(await createLoadAtaInstructions(
    rpc,
    ctokenAta,
    owner.publicKey,
    mint,
    payer.publicKey
  )),
  createUnwrapInstruction(
    ctokenAta,
    splAta,
    owner.publicKey,
    mint,
    amount,
    splInterfaceInfo
  )
);