Płatności zbiorcze

Transakcja Solana to kontener, który zawiera jedną lub więcej instrukcji. Każda instrukcja to operacja — przesłanie tokenów, utworzenie konta, wywołanie programu. Sieć wykonuje wszystkie instrukcje w transakcji sekwencyjnie i atomowo: albo każda instrukcja zakończy się powodzeniem, albo cała transakcja zostanie odrzucona i cofnięta.

Oznacza to, że możesz spakować wiele przelewów w jedną transakcję. Zamiast wysyłać trzy oddzielne transakcje, aby zapłacić trzem odbiorcom, wysyłasz jedną transakcję z trzema instrukcjami przelewu. To szybsze (jedno potwierdzenie zamiast trzech) i tańsze (jedna opłata bazowa zamiast trzech). Poniżej znajduje się przykładowa ilustracja, jak płatności (w tym obrazie nazywane „dropami”) są grupowane w jedną transakcję, a wiele transakcji jest wysyłanych, aby obsłużyć większą partię.

Schemat płatności zbiorczychSchemat płatności zbiorczych

Źródło: QuickNode - Jak wysyłać transakcje zbiorcze na Solanie

Więcej informacji o transakcjach i instrukcjach znajdziesz w przewodnikach Transakcje oraz Instrukcje.

Poniższy przewodnik pokazuje, jak załadować wiele instrukcji przelewu do jednej transakcji w celu realizacji płatności zbiorczych.

Grupowanie instrukcji w jednej transakcji

Transakcja Solana może zawierać wiele przelewów do różnych odbiorców. Podpisujesz tylko raz, płacisz jedną opłatę transakcyjną, a wszystkie przelewy są rozliczane razem. Jeśli którykolwiek przelew się nie powiedzie, cała transakcja zostaje odrzucona.

Zobacz Jak działają płatności na Solanie, aby poznać podstawowe pojęcia dotyczące płatności.

Grupowanie wielu przelewów wymaga osobnego zbudowania każdej instrukcji, a następnie połączenia ich w jednej transakcji.

Poniższe kroki pokazują główny przebieg. Pełny, działający kod znajdziesz w sekcji Demo.

Wyprowadź konta tokenów

Najpierw wyprowadź adresy Associated Token Account (ATA) dla nadawcy oraz każdego odbiorcy. ATA to deterministyczne adresy oparte na portfelu i mincie.

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
});

Utwórz instrukcje transferu

Utwórz osobną instrukcję transferu dla każdego odbiorcy. Każda instrukcja określa:

  • adres źródłowego token account
  • adres docelowego token account
  • autoryzację (adres właściciela źródłowego token account)
  • kwotę w jednostkach bazowych (skorygowaną o liczbę miejsc po przecinku dla danego mintu)
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
});
const transfer1Instruction = getTransferInstruction({
source: senderAta,
destination: recipient1Ata,
authority: sender.address,
amount: 250_000n
});
const transfer2Instruction = getTransferInstruction({
source: senderAta,
destination: recipient2Ata,
authority: sender.address,
amount: 250_000n
});

Wyślij jako jedną transakcję

Dodaj wszystkie instrukcje transferu do jednej transakcji. Dzięki temu wszystkie transfery zostaną wykonane atomowo — albo wszystkie się powiodą, albo cała transakcja zostanie odrzucona.

Zweryfikuj salda

Po przeprowadzeniu transferu zbiorczego zweryfikuj salda tokenów dla wszystkich stron za pomocą pomocnika 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
});
const transfer1Instruction = getTransferInstruction({
source: senderAta,
destination: recipient1Ata,
authority: sender.address,
amount: 250_000n
});
const transfer2Instruction = getTransferInstruction({
source: senderAta,
destination: recipient2Ata,
authority: sender.address,
amount: 250_000n
});
const signature = await client.transaction.prepareAndSend({
authority: sender,
instructions: [transfer1Instruction, transfer2Instruction],
version: 0
});
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);

Wyprowadź konta tokenów

Najpierw wyprowadź adresy Associated Token Account (ATA) dla nadawcy oraz każdego odbiorcy. ATA to deterministyczne adresy oparte na portfelu i mincie.

Utwórz instrukcje transferu

Utwórz osobną instrukcję transferu dla każdego odbiorcy. Każda instrukcja określa:

  • adres źródłowego token account
  • adres docelowego token account
  • autoryzację (adres właściciela źródłowego token account)
  • kwotę w jednostkach bazowych (skorygowaną o liczbę miejsc po przecinku dla danego mintu)

Wyślij jako jedną transakcję

Dodaj wszystkie instrukcje transferu do jednej transakcji. Dzięki temu wszystkie transfery zostaną wykonane atomowo — albo wszystkie się powiodą, albo cała transakcja zostanie odrzucona.

Zweryfikuj salda

Po przeprowadzeniu transferu zbiorczego zweryfikuj salda tokenów dla wszystkich stron za pomocą pomocnika 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.

Skalowanie dzięki planowaniu transakcji

Pojedyncza transakcja ma ograniczenia rozmiaru — około 1232 bajtów. Przy dużych operacjach zbiorczych (np. wypłaty dla setek pracowników, masowe airdropy) przekroczysz ten limit i będziesz musiał podzielić pracę na kilka transakcji.

Możesz oczywiście stworzyć własną logikę rozdzielania transakcji, ale pakiet @solana/instruction-plans (część Solana Kit) obsługuje to na dwóch poziomach:

Plany instrukcji definiują operacje oraz ograniczenia dotyczące ich kolejności:

  • Sekwencyjne — instrukcje, które muszą być wykonane w określonej kolejności
  • Równoległe — instrukcje, które mogą być wykonane w dowolnej kolejności
  • Niedzielne — instrukcje, które muszą pozostać razem w tej samej transakcji

Plany transakcji są generowane na podstawie planów instrukcji. Planer inteligentnie pakuje instrukcje w transakcje o optymalnym rozmiarze, zachowując Twoje ograniczenia dotyczące kolejności. Otrzymany plan transakcji może być:

  • Wykonany — podpisany i wysłany do sieci, przy czym transakcje równoległe są wysyłane jednocześnie
  • Symulowany — testowo uruchomiony w sieci w celu weryfikacji przed wysłaniem
  • Serializowany — skompilowany do formatu base64 dla zewnętrznych usług podpisywania lub procesów wielostronnych

To dwupoziomowe podejście pozwala myśleć w kategoriach operacji ("przelej do Alice, potem przelej do Boba"), podczas gdy biblioteka zajmuje się mechaniką doboru rozmiaru transakcji, pakowaniem i równoległym wykonywaniem.

Is this page helpful?

Spis treści

Edytuj stronę

Zarządzane przez

© 2026 Solana Foundation.
Wszelkie prawa zastrzeżone.
Bądź na bieżąco