Ir al contenido principal

¿Qué es la extensión Solana Transfer Hook?

Actualizado el
1 de mayo de 2026

7 minutos de lectura

Resumen

El Programa de tokens de Solana es un estándar para crear y gestionar tokens en la cadena de bloques de Solana. En 2022, Solana Labs lanzó un nuevo conjunto de funciones, las «Token Extensions», que permiten personalizar el funcionamiento de cualquier token específico.

Una de estas extensiones es el «Transfer Hook», que permite a los desarrolladores añadir lógica personalizada a las transferencias de tokens. En esta guía, analizaremos el «Transfer Hook», cómo funciona y cómo podrías utilizarlo en tu programa de tokens de Solana.

Requisitos previos

Antes de leer esta guía, te recomendamos que te familiarices un poco con los siguientes temas:

¿Qué es un gancho de transferencia?

Los ganchos de transferencia requieren que se ejecute una lógica personalizada cuando se produce una transferencia de tokens. Por ejemplo, es posible que quieras:

  • comprobar que tanto la cuenta del remitente como la del destinatario hayan superado el proceso de verificación KYC antes de autorizar la transferencia,
  • aplicar una estructura de impuestos o regalías que varíe en función de la cantidad de tokens que se transfieran, o
  • actualizar dinámicamente los metadatos de un NFT (consulta nuestra guía sobre «Cómo acuñar un NFT de Solana con la extensión Metadata»)

Las posibilidades de lo que se puede hacer con los ganchos de transferencia son infinitas: todo depende realmente de tu imaginación y de las necesidades de tu proyecto. Una ficha con un gancho de transferencia tiene tres elementos principales:

  • Creación de tokens con la extensión «token hook»
  • Una lista de cuentas meta que especifica las cuentas sobre las que actuará la instrucción del programa de enlace de transferencia
  • Una instrucción del programa «transfer hook» para especificar la lógica personalizada que debe ejecutarse cuando se produce una transferencia de tokens. Si utilizas versiones anteriores de Anchor (anteriores a la v. 0.30), también necesitarás un solución alternativa función para gestionar el gancho de transferencia.

Analicemos con más detalle cada uno de estos elementos.

Creación de tokens con la extensión Token Hook

Para utilizar los ganchos de transferencia, debes crear un token SPL mediante el TOKEN_2022_PROGRAM_ID (ya que las extensiones no funcionan en versiones anteriores del programa de tokens). Al igual que todas las extensiones, la extensión «transfer hook» debe inicializarse al crear el token.

La extensión del gancho de transferencia en sí es bastante sencilla; consta de dos partes:

  1. Un identificador de programa que se encargará de la lógica personalizada y
  2. Una entidad con competencia para realizar modificaciones en esta extensión
solana-program-library/token/program-2022/src/extension/transfer_hook/instruction.rs
pub struct InitializeInstructionData {
/// The public key for the account that can update the program id
pub authority: OptionalNonZeroPubkey,
/// The program id that performs logic during transfers
pub program_id: OptionalNonZeroPubkey,
}

Fuente: GitHub - Programa de tokens SPL de Solana

El programa aprobado debe incluir una instrucción de gancho de transferencia que se activará cuando se produzca una transferencia de tokens. La complejidad y la diversión residen en la lógica personalizada que se incluya dentro del propio gancho. Lo veremos en un momento, pero primero debemos pensar en las cuentas que necesitará el gancho de transferencia. Veamos eso a continuación.

Estructura del gancho de transferencia

Cada transferencia de tokens (independientemente de si se utilizan o no los «transfer hooks») requiere varias cuentas:

  • La cuenta de tokens de origen desde la que se transfieren los tokens
  • La emisión de los tokens que se van a transferir
  • La cuenta de destino a la que se transfieren los tokens
  • El titular de la cuenta del token de origen

Los ganchos de transferencia requieren al menos una cuenta más, una ExtraAccountMetaList cuenta. Esta cuenta almacena información sobre cualquier cuenta adicional que deba pasarse a la transacción en tiempo de ejecución para ejecutar el gancho de transferencia. Esta cuenta se inicializa con el literal de cadena «extra-account-metas» y la clave pública de la casa de moneda, y utiliza el ID de programa del gancho de transferencia específico:

const [pda] = ClavePública.findProgramAddressSync(
[Buffer.desde(«extra-account-metas»), mint.publicKey.toBuffer()],
programa.programId, // ID del programa de conexión de transferencia
);

En conjunto, estos relatos crean un TransferHook el contexto que se pasa a la instrucción del programa del gancho de transferencia. Por ejemplo:

#[derive(Accounts)]
pub struct TransferHook<'info> {
#[account(
token::mint = mint,
token::authority = owner,
)]
pub source_token: InterfaceAccount<'info, TokenAccount>,

pub mint: InterfaceAccount<'info, Mint>,

#[account(
token::mint = mint,
)]
pub destination_token: InterfaceAccount<'info, TokenAccount>,

/// CHECK: source token account owner, can be SystemAccount or PDA owned by another program
pub owner: UncheckedAccount<'info>,

/// CHECK: ExtraAccountMetaList Account,
#[account(
seeds = [b"extra-account-metas", mint.key().as_ref()],
bump
)]
pub extra_account_meta_list: UncheckedAccount<'info>,

// Add any additional accounts below 👇
}

Instrucciones para el gancho de transferencia

El «hook» de transferencia es una instrucción de programa que se activa cuando se produce una transferencia de tokens. Esta instrucción se denomina «hook» y se ejecuta de forma atómica junto con la transferencia de tokens. Esto significa que la transferencia también fallará si falla el «hook». Los «hooks» de transferencia pueden realizar cualquier número de operaciones para aplicar la lógica de negocio, como exigir que un usuario haya completado el proceso de KYC para poder transferir tokens, o añadir funcionalidades adicionales a una transferencia de tokens, como actualizar una cuenta independiente para registrar los detalles de la transferencia. Veamos un par de ejemplos sencillos para hacernos una idea de cómo funcionan los ganchos de transferencia.

A continuación se muestra un ejemplo que comprueba si un usuario está autorizado a realizar una transferencia:

#[error_code]
pub enum MyError {
#[msg("The user is not authorized")]
Unauthorized,
}

#[interface(spl_transfer_hook_interface::execute)]
pub fn transfer_hook(ctx: Context<TransferHook>, amount: u64) -> Result<()> {

let authorized = ctx.accounts.user.authorized;

if !authorized {
return err!(MyError::Unauthorized);
}

Ok(())
}

Aquí tienes otro ejemplo que comprueba si la transferencia se está realizando dentro de un horario de negociación predefinido:

#[error_code]
pub enum MyError {
#[msg("Outside of allowable trading hours")]
OutsideTradingHours,
}

#[interface(spl_transfer_hook_interface::execute)]
pub fn transfer_hook(ctx: Context<TransferHook>, amount: u64) -> Result<()> {
let timestamp = Clock::get()?.unix_timestamp;
let day = Clock::get()?.days_from_unix_epoch % 7;
let hour = (timestamp % 86400) / 3600;
let is_trading_hours = day < 5 && hour >= 5 && hour < 17;

if !is_trading_hours {
return err!(MyError::OutsideTradingHours);
}

Ok(())
}

En cada uno de los ejemplos anteriores, si no se cumple la condición, la transferencia fallará. En eso radica el poder de los «transfer hooks»: te permiten aplicar una lógica personalizada a las transferencias de tokens. Ten en cuenta que el #[interfaz] Se ha añadido la macro a Anchor 0.30.0 y se utiliza para anular el discriminador de instrucciones predeterminado de Anchor y utilizar el discriminador de la instrucción de la interfaz (de modo que no sea necesario utilizar un solución alternativa función).

Solución alternativa

Si utilizas versiones anteriores de Anchor (anteriores a la versión 0.30.0), también tendrás que incluir un solución alternativa función en tu programa para gestionar el gancho de transferencia. Esta función es necesaria debido a las diferencias en la forma en que el programa nativo de Solana y los programas de Anchor gestionan los discriminadores de instrucciones.

// fallback instruction handler as workaround to anchor instruction discriminator check
pub fn fallback<'info>(
program_id: &Pubkey,
accounts: &'info [AccountInfo<'info>],
data: &[u8],
) -> Result<()> {
let instruction = TransferHookInstruction::unpack(data)?;

// match instruction discriminator to transfer hook interface execute instruction
// token2022 program CPIs this instruction on token transfer
match instruction {
TransferHookInstruction::Execute { amount } => {
let amount_bytes = amount.to_le_bytes();

// invoke custom transfer hook instruction on our program
__private::__global::transfer_hook(program_id, accounts, &amount_bytes)
}
_ => return Err(ProgramError::InvalidInstructionData.into()),
}
}

¿Ya te ha enganchado?

Los «transfer hooks» son una forma muy eficaz de añadir lógica personalizada a tus transferencias de tokens. Te permiten aplicar la lógica de negocio, añadir funcionalidades adicionales y crear un programa de tokens más seguro y robusto. Si quieres añadir lógica personalizada a tus transferencias de tokens, los «transfer hooks» son un excelente punto de partida. En nuestra próxima guía, crearemos un programa de ejemplo con «transfer hooks» para mostrar cómo funcionan en la práctica. ¡No te lo pierdas!

Si tienes alguna pregunta, no dudes en utilizar nuestro canal específico en Discord o enviarnos tus comentarios a través del formulario que aparece a continuación. Mantente al día de las últimas novedades siguiéndonos en Twitter y en nuestro canal de anuncios de Telegram.

¡Nos encanta recibir comentarios!

Si tienes algún comentario o sugerencia sobre nuevos temas, no dudes en hacérnoslo saber. Nos encantaría saber tu opinión.

Recursos adicionales

Comparte esta guía