Paiements groupés

Une transaction Solana est un conteneur qui contient une ou plusieurs instructions. Chaque instruction est une opération : transférer des jetons, créer un compte, appeler un programme. Le réseau exécute toutes les instructions d'une transaction de manière séquentielle et atomique : soit chaque instruction réussit, soit la transaction entière échoue et est annulée.

Cela signifie que vous pouvez regrouper plusieurs transferts dans une seule transaction. Au lieu d' envoyer trois transactions distinctes pour payer trois destinataires, vous envoyez une transaction avec trois instructions de transfert. C'est plus rapide (une confirmation au lieu de trois) et moins cher (un seul frais de base au lieu de trois). Voici un exemple illustratif de la façon dont les paiements (appelés "drops" dans cette image) sont regroupés dans une seule transaction et comment plusieurs transactions sont envoyées pour gérer le lot plus important.

Diagramme des paiements groupésDiagramme des paiements groupés

Source : QuickNode - How to Send Bulk Transactions on Solana

Pour plus d'informations sur les transactions et les instructions, consultez les guides Transactions et Instructions.

La procédure ci-dessous montre comment charger plusieurs instructions de transfert dans une seule transaction pour les paiements groupés.

Regrouper les instructions dans une seule transaction

Une transaction Solana peut contenir plusieurs transferts vers différents destinataires. Vous signez une fois, payez un seul frais de transaction, et tous les transferts sont réglés ensemble. Si un transfert échoue, la transaction entière est rejetée.

Consultez Comment fonctionnent les paiements sur Solana pour les concepts fondamentaux des paiements.

Le regroupement de plusieurs transferts nécessite de construire chaque instruction séparément, puis de les combiner dans une seule transaction.

Les étapes ci-dessous montrent le flux principal. Consultez la Démo pour le code complet exécutable.

Dériver les comptes de jetons

Tout d'abord, dérivez les adresses de compte de jetons associé (ATA) pour l'expéditeur et chaque destinataire. Les ATA sont des adresses déterministes basées sur le portefeuille et le mint.

Créer les instructions de transfert

Créez une instruction de transfert distincte pour chaque destinataire. Chaque instruction spécifie :

  • l'adresse du compte de jetons source
  • l'adresse du compte de jetons de destination
  • l'autorité (adresse du propriétaire du compte de jetons source)
  • le montant en unités de base (ajusté selon les décimales du mint)

Envoyer en une seule transaction

Ajoutez toutes les instructions de transfert dans une seule transaction. Cela exécute tous les transferts de manière atomique : soit tous les transferts réussissent, soit la transaction entière échoue.

Vérifier les soldes

Après le transfert groupé, vérifiez les soldes de jetons pour toutes les parties en utilisant l'assistant splToken.

Dériver les comptes de jetons

Tout d'abord, dérivez les adresses de compte de jetons associé (ATA) pour l'expéditeur et chaque destinataire. Les ATA sont des adresses déterministes basées sur le portefeuille et le mint.

Créer les instructions de transfert

Créez une instruction de transfert distincte pour chaque destinataire. Chaque instruction spécifie :

  • l'adresse du compte de jetons source
  • l'adresse du compte de jetons de destination
  • l'autorité (adresse du propriétaire du compte de jetons source)
  • le montant en unités de base (ajusté selon les décimales du mint)

Envoyer en une seule transaction

Ajoutez toutes les instructions de transfert dans une seule transaction. Cela exécute tous les transferts de manière atomique : soit tous les transferts réussissent, soit la transaction entière échoue.

Vérifier les soldes

Après le transfert groupé, vérifiez les soldes de jetons pour toutes les parties en utilisant l'assistant 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
});

Démo

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.

Mise à l'échelle avec la planification de transactions

Une seule transaction a des limites de taille — environ 1232 octets. Pour les opérations groupées importantes (paie pour des centaines d'employés, airdrops massifs), vous dépasserez cette limite et devrez répartir le travail sur plusieurs transactions.

Bien que vous soyez libre de créer votre propre logique de distribution de transactions, le package @solana/instruction-plans (faisant partie de Solana Kit) gère cela à deux niveaux :

Les plans d'instructions définissent vos opérations et leurs contraintes d'ordonnancement :

  • Séquentiel — instructions qui doivent s'exécuter dans l'ordre
  • Parallèle — instructions qui peuvent s'exécuter dans n'importe quel ordre
  • Non divisible — instructions qui doivent rester ensemble dans la même transaction

Les plans de transaction sont générés à partir des plans d'instructions. Le planificateur emballe intelligemment les instructions dans des transactions de taille optimale, en respectant vos contraintes d'ordonnancement. Le plan de transaction résultant peut ensuite être :

  • Exécuté — signé et envoyé au réseau, avec les transactions parallèles envoyées simultanément
  • Simulé — exécuté à blanc sur le réseau pour vérification avant l'envoi
  • Sérialisé — compilé en base64 pour les services de signature externes ou les flux de travail multi-parties

Cette approche à deux niveaux vous permet de penser en termes d'opérations (« transférer à Alice, puis transférer à Bob ») tandis que la bibliothèque gère les mécanismes de dimensionnement des transactions, d'emballage et d'exécution parallèle.

Is this page helpful?

Table des matières

Modifier la page

Géré par

© 2026 Fondation Solana.
Tous droits réservés.
Restez connecté