Pagos por lotes

Una transacción de Solana es un contenedor que contiene una o más instrucciones. Cada instrucción es una operación: transferir tokens, crear una cuenta, llamar a un programa. La red ejecuta todas las instrucciones en una transacción de forma secuencial y atómica: o todas las instrucciones tienen éxito, o la transacción completa falla y se revierte.

Esto significa que puedes empaquetar múltiples transferencias en una sola transacción. En lugar de enviar tres transacciones separadas para pagar a tres destinatarios, envías una transacción con tres instrucciones de transferencia. Esto es más rápido (una confirmación en lugar de tres) y más económico (una tarifa base en lugar de tres). Aquí hay un ejemplo ilustrativo de cómo los pagos (denominados "drops" en esta imagen) se agrupan en una sola transacción y se envían múltiples transacciones para manejar el lote más grande.

Diagrama de pagos por lotesDiagrama de pagos por lotes

Fuente: QuickNode - Cómo enviar transacciones masivas en Solana

Para más información sobre transacciones e instrucciones, consulta las guías de Transacciones e Instrucciones.

El tutorial a continuación muestra cómo cargar múltiples instrucciones de transferencia en una sola transacción para pagos por lotes.

Agrupar instrucciones en una sola transacción

Una transacción de Solana puede contener múltiples transferencias a diferentes destinatarios. Firmas una vez, pagas una tarifa de transacción, y todas las transferencias se liquidan juntas. Si alguna transferencia falla, la transacción completa es rechazada.

Consulta Cómo funcionan los pagos en Solana para conceptos básicos de pagos.

Agrupar múltiples transferencias requiere construir cada instrucción por separado, luego combinarlas en una sola transacción.

Los pasos a continuación muestran el flujo principal. Consulta la Demo para código completo ejecutable.

Derivar cuentas de tokens

Primero, deriva las direcciones de las cuentas de tokens asociadas (ATA) para el remitente y cada destinatario. Las ATA son direcciones determinísticas basadas en la billetera y el mint.

Crear instrucciones de transferencia

Crea una instrucción de transferencia separada para cada destinatario. Cada instrucción especifica:

  • dirección de la cuenta de tokens de origen
  • dirección de la cuenta de tokens de destino
  • autoridad (dirección del propietario de la cuenta de tokens de origen)
  • cantidad en unidades base (ajustada para los decimales del mint)

Enviar como transacción única

Agrega todas las instrucciones de transferencia en una sola transacción. Esto ejecuta todas las transferencias de forma atómica, o todas las transferencias tienen éxito o toda la transacción falla.

Verificar saldos

Después de la transferencia por lotes, verifica los saldos de tokens para todas las partes usando el helper splToken.

Derivar cuentas de tokens

Primero, deriva las direcciones de las cuentas de tokens asociadas (ATA) para el remitente y cada destinatario. Las ATA son direcciones determinísticas basadas en la billetera y el mint.

Crear instrucciones de transferencia

Crea una instrucción de transferencia separada para cada destinatario. Cada instrucción especifica:

  • dirección de la cuenta de tokens de origen
  • dirección de la cuenta de tokens de destino
  • autoridad (dirección del propietario de la cuenta de tokens de origen)
  • cantidad en unidades base (ajustada para los decimales del mint)

Enviar como transacción única

Agrega todas las instrucciones de transferencia en una sola transacción. Esto ejecuta todas las transferencias de forma atómica, o todas las transferencias tienen éxito o toda la transacción falla.

Verificar saldos

Después de la transferencia por lotes, verifica los saldos de tokens para todas las partes usando el helper splToken.

Batch Payments
const [senderAta] = await findAssociatedTokenPda({
mint: mint.address,
owner: sender.address,
tokenProgram: TOKEN_2022_PROGRAM_ADDRESS
});
const [recipient1Ata] = await findAssociatedTokenPda({
mint: mint.address,
owner: recipient1.address,
tokenProgram: TOKEN_2022_PROGRAM_ADDRESS
});
const [recipient2Ata] = await findAssociatedTokenPda({
mint: mint.address,
owner: recipient2.address,
tokenProgram: TOKEN_2022_PROGRAM_ADDRESS
});

Demo

Demo
// Generate keypairs for sender and two recipients
const sender = (await generateKeypair()).signer;
const recipient1 = (await generateKeypair()).signer;
const recipient2 = (await generateKeypair()).signer;
console.log("Sender Address:", sender.address);
console.log("Recipient 1 Address:", recipient1.address);
console.log("Recipient 2 Address:", recipient2.address);
// Demo Setup: Create client, mint account, token accounts, and fund with initial tokens
const { client, mint } = await demoSetup(sender, recipient1, recipient2);
console.log("\nMint Address:", mint.address);
// Derive the Associated Token Accounts addresses (ATAs) for sender and recipients
const [senderAta] = await findAssociatedTokenPda({
mint: mint.address,
owner: sender.address,
tokenProgram: TOKEN_2022_PROGRAM_ADDRESS
});
const [recipient1Ata] = await findAssociatedTokenPda({
mint: mint.address,
owner: recipient1.address,
tokenProgram: TOKEN_2022_PROGRAM_ADDRESS
});
const [recipient2Ata] = await findAssociatedTokenPda({
mint: mint.address,
owner: recipient2.address,
tokenProgram: TOKEN_2022_PROGRAM_ADDRESS
});
console.log("Sender Token Account:", senderAta.toString());
console.log("Recipient 1 Token Account:", recipient1Ata.toString());
console.log("Recipient 2 Token Account:", recipient2Ata.toString());
// =============================================================================
// Batch Token Payment Demo
// =============================================================================
// Create instructions to transfer tokens from sender to both recipients
// Transferring 250,000 base units = 0.25 tokens (with 6 decimals) to each
const transfer1Instruction = getTransferInstruction({
source: senderAta,
destination: recipient1Ata,
authority: sender.address,
amount: 250_000n // 0.25 tokens
});
const transfer2Instruction = getTransferInstruction({
source: senderAta,
destination: recipient2Ata,
authority: sender.address,
amount: 250_000n // 0.25 tokens
});
// Prepare and send both transfers in a single transaction using @solana/client
const signature = await client.transaction.prepareAndSend({
authority: sender,
instructions: [transfer1Instruction, transfer2Instruction],
version: 0
});
console.log("\n=== Batch Token Payment Complete ===");
console.log("Transaction Signature:", signature.toString());
// Fetch final token account balances using @solana/client SPL token helper
const splToken = client.splToken({
mint: mint.address,
tokenProgram: "auto"
});
const senderBalance = await splToken.fetchBalance(sender.address);
const recipient1Balance = await splToken.fetchBalance(recipient1.address);
const recipient2Balance = await splToken.fetchBalance(recipient2.address);
console.log("\nSender Token Account Balance:", senderBalance);
console.log("Recipient 1 Token Account Balance:", recipient1Balance);
console.log("Recipient 2 Token Account Balance:", recipient2Balance);
// =============================================================================
// Demo Setup Helper Function
// =============================================================================
Console
Click to execute the code.

Escalado con planificación de transacciones

Una sola transacción tiene límites de tamaño: aproximadamente 1232 bytes. Para operaciones por lotes grandes (nómina para cientos de empleados, airdrops masivos), excederás este límite y necesitarás dividir el trabajo en múltiples transacciones.

Aunque puedes crear tu propia lógica de distribución de transacciones, el paquete @solana/instruction-plans (parte de Solana Kit) maneja esto en dos niveles:

Los planes de instrucciones definen tus operaciones y sus restricciones de orden:

  • Secuencial — instrucciones que deben ejecutarse en orden
  • Paralelo — instrucciones que pueden ejecutarse en cualquier orden
  • No divisible — instrucciones que deben permanecer juntas en la misma transacción

Los planes de transacciones se generan a partir de los planes de instrucciones. El planificador empaqueta inteligentemente las instrucciones en transacciones de tamaño óptimo, respetando tus restricciones de orden. El plan de transacción resultante puede entonces ser:

  • Ejecutado — firmado y enviado a la red, con transacciones paralelas enviadas simultáneamente
  • Simulado — ejecución de prueba contra la red para verificar antes de enviar
  • Serializado — compilado a base64 para servicios de firma externos o flujos de trabajo multipartitos

Este enfoque de dos niveles te permite pensar en términos de operaciones ("transferir a Alice, luego transferir a Bob") mientras la biblioteca maneja la mecánica del dimensionamiento de transacciones, empaquetado y ejecución paralela.

Is this page helpful?

Tabla de Contenidos

Editar Página

Gestionado por

© 2026 Fundación Solana.
Todos los derechos reservados.
Conéctate