Getting Started with Solana Token Extensions (Token-2022)
**Category:** Development Tutorial
**Audience:** Intermediate Developers
**Reading Time:** 17 minutes
**Verified Packages:** @solana/spl-token@0.4.14, @solana/web3.js@1.98.4, @solana/kit@5.3.0, @solana-program/token-2022@0.6.1
What You'll Learn
Learn how to build getting started with solana token extensions (token-2022). This practical guide covers understand what token extensions are and why they matt
Key Takeaways:
• Understand what Token Extensions are and why they matter
• Create tokens with MemoTransfer and NonTransferable extensions
• Use the latest @solana/kit and @solana-program/token-2022 packages
• Avoid common pitfalls when working with Token-2022
Prerequisites
- Node.js 18+
- Basic understanding of Solana accounts and transactions
- Familiarity with SPL Token program
- TypeScript/JavaScript knowledge
Core Concepts
Token Extensions (Token-2022) is Solana's next-generation token program that adds programmable features to SPL tokens. Unlike the original SPL Token program, Token-2022 supports token-2022 supports 16+ extension types including memotransfer, nontransferable, transferhook, and confidentialtransfer.
Why Token Extensions?
- **MemoTransfer**: Require memos for compliance/tracking
- **NonTransferable**: Create soulbound tokens (certificates, badges)
- **TransferHook**: Execute custom logic on every transfer
- **ConfidentialTransfer**: Privacy-preserving token transfers
- **MetadataPointer**: On-chain metadata without Metaplex
Project Setup
# Create new project
mkdir token-extensions-demo && cd token-extensions-demo
npm init -y
# Install dependencies (verified versions)
npm install @solana/spl-token@0.4.14
npm install @solana/web3.js@1.98.4
npm install @solana/kit@5.3.0
npm install @solana-program/token-2022@0.6.1Implementation
Creating a Token with MemoTransfer Extension
The following code creates a Token-2022 mint with the MemoTransfer extension enabled:
import {
airdropFactory,
appendTransactionMessageInstructions,
createSolanaRpc,
createSolanaRpcSubscriptions,
createTransactionMessage,
generateKeyPairSigner,
lamports,
pipe,
sendAndConfirmTransactionFactory,
setTransactionMessageFeePayerSigner,
setTransactionMessageLifetimeUsingBlockhash,
signTransactionMessageWithSigners
} from "@solana/kit";
import { getCreateAccountInstruction } from "@solana-program/system";
import {
getInitializeMintInstruction,
getMintSize,
TOKEN_2022_PROGRAM_ADDRESS,
extension,
getTokenSize,
findAssociatedTokenPda,
getCreateAssociatedTokenInstructionAsync,
getEnableMemoTransfersInstruction,
getInitializeAccountInstruction,
getMintToInstruction
} from "@solana-program/token-2022";
// Create Connection
const rpc = createSolanaRpc("https://api.mainnet-beta.solana.com");
const rpcSubscriptions = createSolanaRpcSubscriptions("wss://api.mainnet-beta.solana.com");
// Generate keypairs
const authority = await generateKeyPairSigner();
const mint = await generateKeyPairSigner();
// Get mint size and rent
const space = BigInt(getMintSize());
const rent = await rpc.getMinimumBalanceForRentExemption(space).send();
// Create mint account instruction
const createMintAccountInstruction = getCreateAccountInstruction({
payer: authority,
newAccount: mint,
lamports: rent,
space,
programAddress: TOKEN_2022_PROGRAM_ADDRESS
});
// Initialize mint instruction
const initializeMintInstruction = getInitializeMintInstruction({
mint: mint.address,
decimals: 9,
mintAuthority: authority.address
});
// Create token account with MemoTransfer extension
const tokenAccount = await generateKeyPairSigner();
const memoTransferExtension = extension("MemoTransfer", {
requireIncomingTransferMemos: true
});
const tokenAccountLen = BigInt(getTokenSize([memoTransferExtension]));
const tokenAccountRent = await rpc
.getMinimumBalanceForRentExemption(tokenAccountLen)
.send();
const createTokenAccountInstruction = getCreateAccountInstruction({
payer: authority,
newAccount: tokenAccount,
lamports: tokenAccountRent,
space: tokenAccountLen,
programAddress: TOKEN_2022_PROGRAM_ADDRESS
});
const initializeTokenAccountInstruction = getInitializeAccountInstruction({
account: tokenAccount.address,
mint: mint.address,
owner: authority.address
});
const enableMemoTransferInstruction = getEnableMemoTransfersInstruction({
token: tokenAccount.address,
owner: authority
});**Note:** Verified with @solana/kit@5.3.0, @solana-program/token-2022@0.6.1
Best Practices
- Always initialize extensions BEFORE initializing the mint account
- Use getTokenSize() to calculate correct account size with extensions
- Use extension() helper to create properly typed extension configs
- Test on devnet before mainnet deployment
- Consider gas costs - extensions increase account size and rent
Common Pitfalls
- ⚠️ Initializing mint before extensions causes transaction failure
- ⚠️ Forgetting to include extension in account size calculation
- ⚠️ Using old @solana/spl-token instead of @solana-program/token-2022
- ⚠️ Not enabling extension on token account (some extensions need explicit enable)
Resources
- [Solana Token Extensions Documentation](https://solana.com/docs/tokens/extensions)
- [SPL Token-2022 Program](https://spl.solana.com/token-2022)
- [@solana-program/token-2022 npm](https://www.npmjs.com/package/@solana-program/token-2022)
Need help building with Token Extensions? Contact Builderz - we've shipped 32+ Solana projects including custom token implementations.
*Generated with builderz-blog-creator • Research verified: 2026-01-09T16:50:09.545Z*



