Skip to main content
MetadataPointer tells clients where to find a mint’s metadata. TokenMetadata removes the need for a separate metadata account.

Key Parameters

MetadataPointer and TokenMetadata are configured together with these parameters:
ParameterDescription
authorityAccount authorized to update the metadata pointer address.
metadataAddressAccount where metadata is stored. Set to the mint itself to keep metadata on-chain in a single account.
updateAuthorityAccount that can modify token metadata fields after initialization.
nameHuman-readable token name (e.g., “Example Token”).
symbolShort token symbol (e.g., “EXT”).
uriURL pointing to an external JSON file with extended metadata.
additionalMetadataKey-value pairs for custom descriptive fields.
When the MetadataPointer points to the mint itself, TokenMetadata stores name, symbol, URI, and additional fields directly in the mint account data. This produces a self-describing token in a single account. Both extensions work without restrictions in Light Token.

Use MetadataPointer and TokenMetadata With Light Token

Install the agent skill:
npx skills add https://zkcompression.com
See the AI tools guide for dedicated skills.
npm install @lightprotocol/compressed-token@beta \
            @lightprotocol/stateless.js@beta \
            @solana/spl-token
Snippets below assume rpc, payer, mint, owner, recipient, and amount are defined. See the full examples for runnable setup.
import { createRpc } from "@lightprotocol/stateless.js";

const rpc = createRpc(RPC_ENDPOINT);

Create a Token-2022 Mint With Metadata

import {
    Keypair,
    SystemProgram,
    Transaction,
    sendAndConfirmTransaction,
} from "@solana/web3.js";
import { createRpc } from "@lightprotocol/stateless.js";
import { LightTokenProgram } from "@lightprotocol/compressed-token";
import {
    TOKEN_2022_PROGRAM_ID,
    getMintLen,
    createInitializeMint2Instruction,
    ExtensionType,
    createInitializeMetadataPointerInstruction,
} from "@solana/spl-token";
import {
    createInitializeInstruction as createInitializeTokenMetadataInstruction,
    pack,
    TokenMetadata,
} from "@solana/spl-token-metadata";

const rpc = createRpc(RPC_ENDPOINT);

const mintKeypair = Keypair.generate();
const decimals = 9;

const metadata: TokenMetadata = {
    mint: mintKeypair.publicKey,
    name: "Example Token",
    symbol: "EXT",
    uri: "https://example.com/metadata.json",
    additionalMetadata: [],
};

// Calculate space for mint + MetadataPointer extension
const mintLen = getMintLen([ExtensionType.MetadataPointer]);
const metadataLen = pack(metadata).length;
const totalLen = mintLen + metadataLen;
const rentExemptBalance =
    await rpc.getMinimumBalanceForRentExemption(totalLen);

// Create account
const createAccountIx = SystemProgram.createAccount({
    fromPubkey: payer.publicKey,
    lamports: rentExemptBalance,
    newAccountPubkey: mintKeypair.publicKey,
    programId: TOKEN_2022_PROGRAM_ID,
    space: mintLen,
});

// Initialize MetadataPointer (points to the mint itself)
const initMetadataPointerIx = createInitializeMetadataPointerInstruction(
    mintKeypair.publicKey,
    payer.publicKey,
    mintKeypair.publicKey, // metadata address = mint itself
    TOKEN_2022_PROGRAM_ID
);

// Initialize mint
const initMintIx = createInitializeMint2Instruction(
    mintKeypair.publicKey,
    decimals,
    payer.publicKey,
    null,
    TOKEN_2022_PROGRAM_ID
);

// Initialize TokenMetadata on the mint
const initTokenMetadataIx = createInitializeTokenMetadataInstruction({
    programId: TOKEN_2022_PROGRAM_ID,
    mint: mintKeypair.publicKey,
    metadata: mintKeypair.publicKey,
    mintAuthority: payer.publicKey,
    name: metadata.name,
    symbol: metadata.symbol,
    uri: metadata.uri,
    updateAuthority: payer.publicKey,
});

// Register interface PDA with Light Token
const createSplInterfaceIx = await LightTokenProgram.createSplInterface({
    feePayer: payer.publicKey,
    mint: mintKeypair.publicKey,
    tokenProgramId: TOKEN_2022_PROGRAM_ID,
});

const tx = new Transaction().add(
    createAccountIx,
    initMetadataPointerIx,
    initMintIx,
    initTokenMetadataIx,
    createSplInterfaceIx
);

const signature = await sendAndConfirmTransaction(rpc, tx, [
    payer,
    mintKeypair,
]);

Create Interface PDA for Existing Mint

If you already have a Token-2022 mint with MetadataPointer and TokenMetadata, create an interface PDA with Light Token.
import { LightTokenProgram } from "@lightprotocol/compressed-token";
import { TOKEN_2022_PROGRAM_ID } from "@solana/spl-token";

const createSplInterfaceIx = await LightTokenProgram.createSplInterface({
    feePayer: payer.publicKey,
    mint: mintKeypair.publicKey,
    tokenProgramId: TOKEN_2022_PROGRAM_ID,
});

Transfer interface

Wrap and unwrap


Didn’t find what you were looking for?

Reach out! Telegram | email | Discord