Todo ativo tradável na Solana — incluindo os ativos base e quote de todos os pools do Raydium — é um token criado por um dos dois programas: o programa SPL Token legado ou seu sucessor, Token-2022. São programas separados em endereços distintos, com layouts de conta e semântica de extensões diferentes. O Raydium suporta ambos, mas não em todos os lugares: CPMM, CLMM e Farm v6 aceitam mints Token-2022; AMM v4 não. Entender essa divisão é essencial antes de integrar-se com qualquer pool.
Os dois programas
| SPL Token | Token-2022 |
|---|
| Program ID | TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA | TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb |
| Lançado | 2020 | 2022 |
| Tamanho da conta (token account) | 165 B | 165 B + extensões (variável) |
| Extensões | Não | Sim — 17+ extensões oficiais |
| Compatibilidade com versões antigas | Total | Opt-in por mint |
Ambos são mantidos pelo time da Solana Labs (agora Anza) e vivem no repositório solana-program-library.
Por que dois programas?
SPL Token foi congelado para manter compatibilidade com o futuro — seu bytecode é efetivamente imutável, formando uma base limpa para todo o ecossistema. Conforme os casos de uso cresceram (stablecoins querendo cobrar taxas de transferência, mints institucionais precisando de autoridades de congelamento com mais nuances, NFTs precisando de ponteiros de metadados), o time da Solana introduziu Token-2022 como um programa separado e extensível em vez de fazer upgrade do SPL Token. Isso preserva as integrações existentes e permite que cada mint opte exatamente pelas extensões de que precisa.
Token-2022 é um superconjunto estrito em funcionalidade, não em espaço de endereços: os dois programas coexistem, e um mint em um determinado endereço pertence a exatamente um deles.
Estrutura de contas
Conta Mint
Define a identidade de um token.
Mint SPL Token (82 bytes):
u32 mint_authority_option
Pubkey mint_authority
u64 supply
u8 decimals
bool is_initialized
u32 freeze_authority_option
Pubkey freeze_authority
Mint Token-2022: mesmo layout base, mais zero ou mais registros extension TLV (type-length-value) anexados após a base.
Token Account
Mantém um saldo de um mint específico para um proprietário específico.
Conta SPL Token (165 bytes):
Pubkey mint
Pubkey owner
u64 amount
u32 delegate_option
Pubkey delegate
u8 state // initialized, frozen
u32 is_native_option
u64 is_native
u64 delegated_amount
u32 close_authority_option
Pubkey close_authority
Conta Token-2022: mesma base, mais registros TLV de extensão se alguma extensão estiver ativa.
Extensões Token-2022
Extensões são recursos modulares que podem ser anexados a mints ou contas. Cada extensão é um registro TLV separado. As principais para o Raydium:
Transfer fee
O mint pode cobrar uma taxa percentual em cada transferência. A taxa vai para uma autoridade de saque configurada. Suportado pelo Raydium CPMM e CLMM via SwapV2 — o programa leva a taxa em conta ao calcular as taxas de câmbio, então a matemática do pool permanece coerente.
let extension = TransferFeeConfig {
transfer_fee_config_authority,
withdraw_withheld_authority,
withheld_amount: 0,
older_transfer_fee: ...,
newer_transfer_fee: ...,
};
Transfer hook
O mint aponta para um programa que o runtime invoca em cada transferência. O programa hook pode rejeitar a transferência ou executar efeitos colaterais (atualizar um estado de conformidade, registrar, etc.). O Raydium CPMM/CLMM invoca o hook via SwapV2 — a transação inclui o programa hook e quaisquer contas extras de que ele precisa.
Interest-bearing
O saldo on-chain acumula juros em uma taxa configurada. Apenas para exibição (saldos aparecem maiores ao longo do tempo) em vez de ser real; o fornecimento subjacente permanece inalterado.
Mint close authority
Permite que o mint seja fechado uma vez que o fornecimento atinja zero.
Permanent delegate
Uma carteira designada pode transferir ou queimar tokens de qualquer conta incondicionalmente. O Raydium bloqueia a criação de pools para mints com essa extensão — é incompatível com o invariante de que as reservas do pool não podem ser apreendidas.
Non-transferable
Tokens não podem ser movidos da conta em que foram criados. O Raydium bloqueia a criação de pools — um ativo intransmissível não pode ser a base ou quote de um pool de LP.
Default account state
Novas contas de token para esse mint são congeladas por padrão e devem ser descongeladas pela autoridade de congelamento. Usável mas raro.
Confidential transfer
Os saldos e valores de transferência são criptografados. O Raydium não suporta mints de transferência confidencial (a matemática do pool requer saldos em texto simples).
Substitui metadados Metaplex para mints Token-2022. Suportado para listagens de pools Raydium.
Group / Member pointer
Declara um mint como pertencente a um grupo (por exemplo, uma coleção de NFT). Informativo; o Raydium usa isso para exibição.
Veja a página oficial de extensões Token-2022 para a lista completa.
Quais produtos Raydium suportam o quê
| Produto | SPL Token | Token-2022 | Notas |
|---|
| AMM v4 | Sim | Não | A integração OpenBook requer SPL Token |
| CPMM | Sim | Sim | Requer SwapV2 para pools Token-2022 |
| CLMM | Sim | Sim | Requer SwapV2 para pools Token-2022 |
| Farm v6 | Sim | Sim | Suportado para mint de stake e mints de recompensa |
| LaunchLab | Sim | Sim | Pools CPMM graduados herdam suporte Token-2022 |
Elegibilidade de mint para pools Raydium — todas as extensões permitidas a menos que listadas:
- Bloqueadas: non-transferable, permanent delegate, confidential transfer, default account state (em configurações rejeitadas).
- Permitidas com ressalvas (LP deve aceitar risco): transfer fee, transfer hook, freeze authority ativa.
- Totalmente permitidas: interest-bearing, metadata pointer, group pointer, mint close authority.
A resposta getPoolInfoFromRpc inclui as flags de extensão do mint — clientes devem verificar antes de fornecer liquidez.
Padrões de token account
Associated Token Account (ATA)
Ambos os programas compartilham a convenção Associated Token Account: um PDA derivado de [owner, programId, mint] via o Associated Token Program (ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL). Quase toda conta de token de usuário na Solana é um ATA.
import { getAssociatedTokenAddressSync } from "@solana/spl-token";
// SPL Token
const ata = getAssociatedTokenAddressSync(mint, owner);
// Token-2022
const ata22 = getAssociatedTokenAddressSync(
mint,
owner,
false, // allowOwnerOffCurve
TOKEN_2022_PROGRAM_ID,
);
O programa ATA cria contas pertencentes ao programa de token apropriado com base em qual programa é proprietário do mint.
Token accounts não-ATA
Uma carteira pode ter múltiplas contas de token para um único mint; ATA é apenas a convenção. Vaults de pools, por exemplo, não são ATAs — são PDAs do programa do pool, mantendo as reservas do pool.
Detectando a qual programa um mint pertence
Toda conta de mint tem um campo owner apontando para SPL Token ou Token-2022:
const mintInfo = await connection.getAccountInfo(mintPubkey);
if (mintInfo.owner.equals(TOKEN_PROGRAM_ID)) {
console.log("SPL Token mint");
} else if (mintInfo.owner.equals(TOKEN_2022_PROGRAM_ID)) {
console.log("Token-2022 mint");
}
O SDK Raydium lida com essa detecção automaticamente — getPoolInfoFromRpc retorna o programId apropriado por token para que os clientes construam ATAs corretas.
Instruções swap por programa
CPMM e CLMM do Raydium cada uma tem duas instruções de swap:
| Instrução | Mints suportados |
|---|
Swap / SwapBaseInput (legado) | Apenas SPL Token |
SwapV2 / SwapBaseInputV2 | Ambos SPL Token e Token-2022 |
SwapV2 aceita contas adicionais: contas de mint para ambos os lados, o programa de token para cada lado (já que podem ser diferentes), e — para mints com transfer hook — o programa hook e suas contas obrigatórias.
Clientes devem sempre usar SwapV2 quando pelo menos um lado for Token-2022; SwapV2 também funciona para pools somente SPL, mas o Swap legado é mais barato em compute.
O SDK escolhe a variante correta automaticamente.
Migrando um projeto SPL Token para Token-2022
Token-2022 não é um substituto direto no nível de mint — um mint no endereço X é ou SPL ou Token-2022, e isso é fixado na criação. Para “migrar” você deve:
- Criar um novo mint sob Token-2022 com as extensões que você quer.
- Fornecer um mecanismo de swap/wrap para que detentores do mint SPL antigo troquem pelo novo.
- Atualizar todos os pools de LP, farms e integrações para fazer referência ao novo mint.
Isso é pesado. A maioria dos projetos lançados em SPL permanecem em SPL a menos que uma necessidade de extensão específica force a mudança.
import {
Connection, Keypair, SystemProgram, Transaction, sendAndConfirmTransaction,
} from "@solana/web3.js";
import {
TOKEN_2022_PROGRAM_ID, ExtensionType, createInitializeMintInstruction,
getMintLen, createInitializeTransferFeeConfigInstruction,
} from "@solana/spl-token";
const connection = new Connection("https://api.mainnet-beta.solana.com");
const payer = Keypair.generate();
const mint = Keypair.generate();
const extensions = [ExtensionType.TransferFeeConfig];
const mintLen = getMintLen(extensions);
const rentLamports = await connection.getMinimumBalanceForRentExemption(mintLen);
const tx = new Transaction().add(
SystemProgram.createAccount({
fromPubkey: payer.publicKey,
newAccountPubkey: mint.publicKey,
space: mintLen,
lamports: rentLamports,
programId: TOKEN_2022_PROGRAM_ID,
}),
createInitializeTransferFeeConfigInstruction(
mint.publicKey,
payer.publicKey, // transfer fee authority
payer.publicKey, // withdraw-withheld authority
50, // 50 bps = 0.5%
BigInt(1_000_000), // max fee per transfer (smallest units)
TOKEN_2022_PROGRAM_ID,
),
createInitializeMintInstruction(
mint.publicKey,
9, // decimals
payer.publicKey, // mint authority
null, // freeze authority
TOKEN_2022_PROGRAM_ID,
),
);
await sendAndConfirmTransaction(connection, tx, [payer, mint]);
Esse mint pode ser enviado a um pool CPMM Raydium; os traders pagarão a taxa de transferência de 0,5% além da taxa de swap do pool.
Considerações de segurança
Antes de fornecer liquidez ou fazer swap através de um mint Token-2022:
- Verifique
freeze_authority. Se não for nulo e mantido por uma parte centralizada, eles podem congelar seu ATA (e possivelmente o vault do pool).
- Verifique
transfer_hook. O programa hook pode bloquear transferências arbitrariamente — faça sua própria pesquisa sobre a fonte do hook.
- Verifique
transfer_fee. Leve a taxa em conta na saída esperada do swap.
- Verifique
permanent_delegate e non_transferable. O programa Raydium rejeita estes, mas verifique se estiver construindo uma integração customizada.
Veja security/oracle-and-token-risks para o framework completo de aceitação de risco.
Ponteiros
Fontes: