Cuentas de Token Asociadas (ATA)
Una Cuenta de Token Asociada (ATA) es la dirección canónica de cuenta de token SPL para un par de billetera + emisión. Las billeteras, los programas y los indexadores confían en este PDA determinista en lugar de direcciones de cuenta de token ad hoc.
Receta
import { findAssociatedTokenPda, TOKEN_PROGRAM_ADDRESS } from "@solana-program/token";
import { address } from "@solana/kit";
const [ata] = await findAssociatedTokenPda({
mint: address("MINT_PUBKEY"),
owner: address("WALLET_PUBKEY"),
tokenProgram: TOKEN_PROGRAM_ADDRESS,
});spl-token create-account <MINT>
spl-token address --token <MINT>Cuándo usar esto:
- Para enviar tokens a una clave pública de billetera (no a una dirección de cuenta de token raw).
- Para crear interfaces de depósito que muestren una dirección por activo.
- Para validar cuentas de destinatario en programas on-chain.
- Para financiar ATAs de usuario durante la incorporación.
Ejemplo de Trabajo
import {
createSolanaRpc,
createTransactionMessage,
pipe,
setTransactionMessageFeePayerSigner,
setTransactionMessageLifetimeUsingBlockhash,
appendTransactionMessageInstructions,
signTransactionMessageWithSigners,
sendAndConfirmTransactionFactory,
address,
} from "@solana/kit";
import {
getCreateAssociatedTokenIdempotentInstruction,
findAssociatedTokenPda,
TOKEN_PROGRAM_ADDRESS,
} from "@solana-program/token";
import { ASSOCIATED_TOKEN_PROGRAM_ADDRESS } from "@solana-program/associated-token";
const rpc = createSolanaRpc("https://api.devnet.solana.com");
const mint = address("MINT_PUBKEY");
const owner = address("WALLET_PUBKEY");
const [ata] = await findAssociatedTokenPda({
mint,
owner,
tokenProgram: TOKEN_PROGRAM_ADDRESS,
});
const createAtaIx = getCreateAssociatedTokenIdempotentInstruction({
ata,
mint,
owner,
payer: owner, // firmante del pagador de tarifa en una app real
tokenProgram: TOKEN_PROGRAM_ADDRESS,
associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ADDRESS,
});
// Construir, firmar y enviar con el firmante de tu billetera conectado a los campos de pagador de tarifa y pagador
console.log("ATA:", ata);use anchor_spl::associated_token::AssociatedToken;
use anchor_spl::token::{Mint, Token, TokenAccount};
#[derive(Accounts)]
pub struct InitUserAta<'info> {
pub mint: Account<'info, Mint>,
#[account(
init_if_needed,
payer = payer,
associated_token::mint = mint,
associated_token::authority = user,
)]
pub user_ata: Account<'info, TokenAccount>,
pub user: SystemAccount<'info>,
#[account(mut)]
pub payer: Signer<'info>,
pub token_program: Program<'info, Token>,
pub associated_token_program: Program<'info, AssociatedToken>,
pub system_program: Program<'info, System>,
}Lo que esto demuestra:
- La dirección ATA se deriva del propietario, la emisión y el ID del programa de token.
create_associated_token_account_idempotentes seguro de llamar cuando la ATA puede existir.- Las restricciones de
associated_tokende Anchor conectan la misma derivación on-chain.
Análisis Profundo
Cómo Funciona
- El programa ATA (
ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL) crea cuentas de token en un PDA. - Semillas: clave pública del propietario, ID del programa de token, clave pública de emisión (a través de las reglas del programa de token asociado).
- Las cuentas de token estándar tienen 165 bytes; se requiere financiación exenta de alquiler en la creación.
- Las emisiones Token-2022 utilizan el mismo programa ATA con
TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEbcomo programa de token.
Entradas de Derivación
| Entrada | Rol |
|---|---|
owner | Billetera o PDA que posee la cuenta de token |
mint | Clave pública de emisión SPL |
token_program | ID del programa clásico SPL o Token-2022 |
Notas de Rust
use anchor_spl::associated_token::get_associated_token_address;
let ata = get_associated_token_address(&owner.key(), &mint.key());
// Comparar con la cuenta pasada en rutas de validación manualTrampas
- Programa de token incorrecto en la derivación: la dirección ATA no coincide para las emisiones Token-2022. Solución: pasar el ID real del programa de token de la emisión a
findAssociatedTokenPda. - Enviar a una billetera sin ATA: la transferencia falla. Solución:
--fund-recipienten la CLI ocreateAssociatedTokenIdempotenten clientes. - Asumir una cuenta de token por emisión globalmente: pueden existir múltiples cuentas no ATA. Solución: preferir ATA; validar que la dirección coincide con la derivación en programas.
- El propietario es un PDA: la ATA aún funciona; el propietario es la clave pública del PDA, no una clave de firma. Solución: el programa firma como PDA al mover tokens desde una ATA propiedad del PDA.
- Almacenar en caché el alquiler de ATA: los parámetros del clúster cambian. Solución: consultar
getMinimumBalanceForRentExemption(165).
Alternativas
| Alternativa | Usar Cuándo | No Usar Cuándo |
|---|---|---|
| Cuenta de token no ATA | Integraciones heredadas requieren una dirección fija | UX de billetera estándar |
Patrones getOrCreateAssociatedTokenAccount | Ayudante de cliente de un solo uso | La validación on-chain todavía necesita derivación |
| Token-2022 con extensiones | Mismas reglas ATA | El cliente asume solo el programa Token clásico |
Preguntas Frecuentes
¿Qué es una ATA?
El PDA canónico de cuenta de token asociada para un propietario de billetera y emisión dados. Las billeteras muestran una dirección de depósito por activo SPL.
¿Pueden existir dos ATAs para el mismo propietario y emisión?
No. La derivación es determinista: solo una dirección ATA por triple (propietario, emisión, programa de token).
¿La creación de ATA cuesta SOL?
Sí. El pagador financia lamports exentos de alquiler (~2M para una cuenta de 165 bytes) más la tarifa de transacción.
¿Puede un programa poseer una ATA?
Sí. La clave pública del propietario puede ser un PDA; el programa propietario firma las transferencias con las semillas del PDA.
¿Cómo obtengo la dirección ATA sin crearla?
Derívala con findAssociatedTokenPda / spl-token address --token; la creación es un paso separado.
¿Es segura la creación idempotente para spam?
Sí. La instrucción idempotente tiene éxito independientemente de si la ATA ya existe o no.
¿Las emisiones Token-2022 usan el mismo programa ATA?
Sí, pero pasa el ID del programa Token-2022 en la derivación e instrucciones.
¿Qué pasa si transfiero a una cuenta de token aleatoria?
Funciona si la emisión de la cuenta coincide, pero la UX se rompe: los usuarios esperan direcciones ATA en exploradores y billeteras.
¿Puedo cerrar una ATA?
Sí, cuando el saldo es cero. Los lamports se devuelven a una cuenta de destino.
¿Cómo encuentran los indexadores los tokens de una billetera?
getTokenAccountsByOwner devuelve ATAs y cualquier otra cuenta de token para ese propietario.
¿Deben los protocolos pagar el alquiler de ATA?
Subsidio común de incorporación: presupuestar tesorería para create ATA por usuario por emisión.
¿Incluye @solana/kit 7.0.0 ayudantes de ATA?
Utiliza los paquetes @solana-program/token y @solana-program/associated-token junto con el RPC de kit y los constructores de transacciones.
Relacionado
- Conceptos básicos de SPL Token - emisiones y saldos
- Transferencias y Delegados - mover tokens
- SPL Token en Programas - Restricciones de Anchor
Versiones de la pila: Esta página fue escrita para Agave 4.1.1, Solana CLI 3.0.10, Anchor 0.32.1, anchor-lang 0.32.1, Rust 1.91.1, @solana/kit 7.0.0, Surfpool 0.12.0, y LiteSVM 0.6.x.