Token-2022 (also called Token Extensions) is Solana’s successor to the original SPL Token program. It lives at a different program address and adds optional extension data after the standard mint and token account layouts.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/blueshift-gg/quasar/llms.txt
Use this file to discover all available pages before exploring further.
quasar-spl supports Token-2022 with dedicated account wrappers (Token2022, Mint2022), a shared zero-copy data layout for the base fields, and a unified Interface<TokenInterface> wrapper that accepts either program at runtime.
Program Addresses
Both token program addresses are exported fromquasar-spl:
| Constant | Address |
|---|---|
SPL_TOKEN_ID | TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA |
TOKEN_2022_ID | TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb |
ATA_PROGRAM_ID | ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL |
Token2022Program is the program marker type for Token-2022. Its Id::ID constant is TOKEN_2022_ID:
Account Types for Token-2022
quasar-spl exports two Token-2022-specific wrappers that enforce ownership by TOKEN_2022_ID:
| Wrapper | Owner enforced | Underlying layout |
|---|---|---|
Account<Token2022> | TOKEN_2022_ID only | TokenDataZc (165 bytes) |
Account<Mint2022> | TOKEN_2022_ID only | MintDataZc (82 bytes) |
TokenDataZc and MintDataZc) as their SPL Token counterparts. The base fields — mint, owner, amount, supply, decimals, etc. — are identical at the byte level. Token-2022 extension data, when present, appears after byte 165 (for token accounts) or byte 82 (for mints) and is not parsed by these types.
Token-2022 extension data lives beyond the base 165-byte token / 82-byte mint layout. Quasar-spl gives you zero-copy access to the base fields only. If your program needs to read extension-specific data (e.g. transfer fees, interest-bearing configuration), you must parse the extension TLV region manually.
Using Token-2022 Account Types
SwapToken → Token2022 and Mint → Mint2022, and change the program marker to Token2022Program. All CPI methods remain identical.
MintTo with Token-2022:
Initializing Token-2022 Accounts
The#[account(init, ...)] attribute works identically for Token-2022 types. Swap the type and program marker — everything else is unchanged.
Initialize a Token-2022 mint:
Interface<TokenInterface> — Accepting Either Program
Interface<TokenInterface> is a runtime-polymorphic program marker that accepts both SPL_TOKEN_ID and TOKEN_2022_ID. The TokenInterface struct in spl/src/interface.rs implements ProgramInterface and its matches function approves both addresses. Combined with InterfaceAccount<Token> and InterfaceAccount<Mint>, you can write a single instruction that works with tokens from either program.
- The
token_programaccount’s address is eitherSPL_TOKEN_IDorTOKEN_2022_ID. - Each
InterfaceAccount<Token>is owned by that same program.
Interface<TokenInterface> field dispatches to whichever program address is stored in the account at runtime — there is no branching in user code.
transfer_checked via interface:
Validating Interface Accounts
Thetoken and mint behavior arguments work with InterfaceAccount<T> the same way they work with Account<T>. When token_program = token_program is provided the validator checks that the account is owned by that specific program and that the program is one of the two accepted addresses.
Validate a token account via interface:
Initializing with Interface<TokenInterface>
The init system also works throughInterface<TokenInterface>. At init time the framework reads the program address from the supplied token_program account and dispatches to the correct initialize_account3 or initialize_mint2 instruction:
Choosing the Right Type
- SPL Token only
- Token-2022 only
- Either program
Use
Account<Token> / Account<Mint> with Program<TokenProgram>. The owner is enforced at compile time as SPL_TOKEN_ID. This is the lowest-overhead option when you know the program at design time.Migration: SPL Token → Token-2022
If you are upgrading an existing program to support Token-2022 while keeping backward compatibility with SPL Token, the migration path is:Change account types to InterfaceAccount
Replace
Account<Token> with InterfaceAccount<Token> and Account<Mint> with InterfaceAccount<Mint> in your accounts struct. Both still dereference to the same TokenDataZc / MintDataZc zero-copy view.Change the program marker to Interface<TokenInterface>
Replace
Program<TokenProgram> with Interface<TokenInterface>. All TokenCpi method calls remain identical — no changes to your handler logic.Pass token_program to behavior args
If you use
#[account(token(...))] or #[account(mint(...))] annotations, add token_program = token_program to those args so the validator checks both owner and program address: