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 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.
Demo
// Generate keypairs for sender and two recipientsconst 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 tokensconst { client, mint } = await demoSetup(sender, recipient1, recipient2);console.log("\nMint Address:", mint.address);// Derive the Associated Token Accounts addresses (ATAs) for sender and recipientsconst [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 eachconst 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/clientconst 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 helperconst 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// =============================================================================
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?