Transacties

Om met het Solana-netwerk te communiceren, moet je een transactie versturen. Je kunt een transactie zien als een envelop die verschillende formulieren bevat. Elk formulier is een instructie die het netwerk vertelt wat te doen. Het versturen van de transactie is als het posten van de envelop zodat de formulieren kunnen worden verwerkt.

Het onderstaande voorbeeld toont een vereenvoudigde versie van twee transacties. Wanneer de eerste transactie wordt verwerkt, zal deze één enkele instructie uitvoeren. Wanneer de tweede transactie wordt verwerkt, zal deze drie instructies in opeenvolgende volgorde uitvoeren: eerst instructie 1, gevolgd door instructie 2, gevolgd door instructie 3.

Transacties zijn atomair: als een enkele instructie mislukt, zal de hele transactie mislukken en zullen er geen wijzigingen plaatsvinden.

Een vereenvoudigd diagram dat twee transacties toontEen vereenvoudigd diagram dat twee transacties toont

Een Transaction bevat de volgende informatie:

  • signatures: een array van handtekeningen
  • message: transactie-informatie, inclusief de lijst met instructies die moeten worden verwerkt
Transaction
pub struct Transaction {
#[wasm_bindgen(skip)]
#[serde(with = "short_vec")]
pub signatures: Vec<Signature>,
#[wasm_bindgen(skip)]
pub message: Message,
}

Diagram dat de twee delen van een transactie toontDiagram dat de twee delen van een transactie toont

Transacties hebben een totale groottelimiet van 1232 bytes. Deze limiet omvat zowel de signatures array als de message struct.

Deze limiet is ontworpen om pakketfragmentatie op typische internetinfrastructuur te voorkomen. Hoewel IPv6 MTU's groter dan 9000 bytes ondersteunt, gebruiken de meeste internetrouters een standaard MTU van 1500 bytes (standaard Ethernet). Om ervoor te zorgen dat transacties binnen één pakket passen zonder fragmentatie, gebruikt Solana 1280 bytes (de minimale MTU vereist voor IPv6) minus 48 bytes voor netwerkheaders (40 bytes IPv6 + 8 bytes fragment/UDP-header), wat resulteert in de transactiegrootte limiet van 1232 bytes.

Diagram dat het transactieformaat en de groottelimieten toontDiagram dat het transactieformaat en de groottelimieten toont

Handtekeningen

De signatures array van de transactie bevat Signature structs. Elke Signature is 64 bytes en wordt aangemaakt door de Message van de transactie te ondertekenen met de private key van het account. Een handtekening moet worden verstrekt voor elk signer account dat is opgenomen in een van de instructies van de transactie.

De eerste handtekening behoort tot het account dat de basistarieven van de transactie zal betalen en is de transactiehandtekening. De transactiehandtekening kan worden gebruikt om de details van de transactie op het netwerk op te zoeken.

Bericht

De message van de transactie is een Message struct die de volgende informatie bevat:

  • header: de bericht header
  • account_keys: een array van accountadressen die vereist zijn voor de instructies van de transactie
  • recent_blockhash: een blockhash die fungeert als tijdstempel voor de transactie
  • instructions: een array van instructies

Om ruimte te besparen, slaat de transactie geen rechten op voor elk account afzonderlijk. In plaats daarvan worden accountrechten bepaald met behulp van de header en account_keys.

Message
pub struct Message {
/// The message header, identifying signed and read-only `account_keys`.
pub header: MessageHeader,
/// All the account keys used by this transaction.
#[serde(with = "short_vec")]
pub account_keys: Vec<Pubkey>,
/// The id of a recent ledger entry.
pub recent_blockhash: Hash,
/// Programs that will be executed in sequence and committed in
/// one atomic transaction if all succeed.
#[serde(with = "short_vec")]
pub instructions: Vec<CompiledInstruction>,
}

De header van het bericht is een MessageHeader struct. Deze bevat de volgende informatie:

  • num_required_signatures: het totale aantal handtekeningen dat vereist is voor de transactie
  • num_readonly_signed_accounts: het totale aantal read-only accounts die handtekeningen vereisen
  • num_readonly_unsigned_accounts: het totale aantal read-only accounts die geen handtekeningen vereisen
MessageHeader
pub struct MessageHeader {
/// The number of signatures required for this message to be considered
/// valid. The signers of those signatures must match the first
/// `num_required_signatures` of [`Message::account_keys`].
pub num_required_signatures: u8,
/// The last `num_readonly_signed_accounts` of the signed keys are read-only
/// accounts.
pub num_readonly_signed_accounts: u8,
/// The last `num_readonly_unsigned_accounts` of the unsigned keys are
/// read-only accounts.
pub num_readonly_unsigned_accounts: u8,
}

Diagram met de drie delen van de berichtheaderDiagram met de drie delen van de berichtheader

Accountadressen

De account_keys van het bericht is een array van accountadressen, verzonden in compact array-formaat. Het prefix van de array geeft de lengte aan. Elk item in de array is een publieke sleutel die verwijst naar een account dat door de instructies wordt gebruikt. De accounts_keys-array moet compleet en strikt geordend zijn, als volgt:

  1. Ondertekenaar + Beschrijfbaar
  2. Ondertekenaar + Alleen-lezen
  3. Geen ondertekenaar + Beschrijfbaar
  4. Geen ondertekenaar + Alleen-lezen

Strikte ordening stelt de account_keys-array in staat om gecombineerd te worden met de informatie in de header van het bericht om de rechten voor elk account te bepalen.

Diagram dat de volgorde van de array met accountadressen toontDiagram dat de volgorde van de array met accountadressen toont

Recente blockhash

De recent_blockhash van het bericht is een hashwaarde die fungeert als een transactie- tijdstempel en dubbele transacties voorkomt. Een blockhash verloopt na 150 blokken. (Equivalent aan één minuut—ervan uitgaande dat elk blok 400ms duurt.) Nadat het blok verloopt, is de transactie verlopen en kan deze niet meer worden verwerkt.

De getLatestBlockhash RPC-methode stelt je in staat om de huidige blockhash en de laatste blokhoogte te verkrijgen waarop de blockhash geldig zal zijn.

Instructies

De instructions van het bericht is een array van alle instructies die moeten worden verwerkt, verzonden in compact array-formaat. Het prefix van de array geeft de lengte aan. Elk item in de array is een CompiledInstruction struct en bevat de volgende informatie:

  1. program_id_index: Een index die verwijst naar een adres in de account_keys-array. Deze waarde geeft het adres aan van het programma dat de instructie verwerkt.
  2. accounts: Een array van indices die verwijzen naar adressen in de account_keys-array. Elke index verwijst naar het adres van een account dat vereist is voor deze instructie.
  3. data: Een byte-array die specificeert welke instructie moet worden aangeroepen op het programma. Het bevat ook eventuele aanvullende gegevens die vereist zijn voor de instructie. (Bijvoorbeeld functieargumenten)
CompiledInstruction
pub struct CompiledInstruction {
/// Index into the transaction keys array indicating the program account that executes this instruction.
pub program_id_index: u8,
/// Ordered indices into the transaction keys array indicating which accounts to pass to the program.
#[serde(with = "short_vec")]
pub accounts: Vec<u8>,
/// The program input data.
#[serde(with = "short_vec")]
pub data: Vec<u8>,
}

Compacte array van instructiesCompacte array van instructies

Voorbeeld transactiestructuur

Het volgende voorbeeld toont de structuur van een transactie die een enkele SOL-overdrachtsinstructie bevat.

import {
createSolanaRpc,
generateKeyPairSigner,
lamports,
createTransactionMessage,
setTransactionMessageFeePayerSigner,
setTransactionMessageLifetimeUsingBlockhash,
appendTransactionMessageInstructions,
pipe,
signTransactionMessageWithSigners,
getCompiledTransactionMessageDecoder
} from "@solana/kit";
import { getTransferSolInstruction } from "@solana-program/system";
const rpc = createSolanaRpc("http://localhost:8899");
const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
// Generate sender and recipient keypairs
const sender = await generateKeyPairSigner();
const recipient = await generateKeyPairSigner();
// Define the amount to transfer
const LAMPORTS_PER_SOL = 1_000_000_000n;
const transferAmount = lamports(LAMPORTS_PER_SOL / 100n); // 0.01 SOL
// Create a transfer instruction for transferring SOL from sender to recipient
const transferInstruction = getTransferSolInstruction({
source: sender,
destination: recipient.address,
amount: transferAmount
});
// Create transaction message
const transactionMessage = pipe(
createTransactionMessage({ version: 0 }),
(tx) => setTransactionMessageFeePayerSigner(sender, tx),
(tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
(tx) => appendTransactionMessageInstructions([transferInstruction], tx)
);
const signedTransaction =
await signTransactionMessageWithSigners(transactionMessage);
// Decode the messageBytes
const compiledTransactionMessage =
getCompiledTransactionMessageDecoder().decode(signedTransaction.messageBytes);
console.log(JSON.stringify(compiledTransactionMessage, null, 2));
Console
Click to execute the code.

De onderstaande code toont de uitvoer van de vorige codefragmenten. Het formaat verschilt tussen SDK's, maar merk op dat elke instructie dezelfde vereiste informatie bevat.

{
"version": 0,
"header": {
"numSignerAccounts": 1,
"numReadonlySignerAccounts": 0,
"numReadonlyNonSignerAccounts": 1
},
"staticAccounts": [
"HoCy8p5xxDDYTYWEbQZasEjVNM5rxvidx8AfyqA4ywBa",
"5T388jBjovy7d8mQ3emHxMDTbUF8b7nWvAnSiP3EAdFL",
"11111111111111111111111111111111"
],
"lifetimeToken": "EGCWPUEXhqHJWYBfDirq3mHZb4qDpATmYqBZMBy9TBC1",
"instructions": [
{
"programAddressIndex": 2,
"accountIndices": [0, 1],
"data": {
"0": 2,
"1": 0,
"2": 0,
"3": 0,
"4": 128,
"5": 150,
"6": 152,
"7": 0,
"8": 0,
"9": 0,
"10": 0,
"11": 0
}
}
]
}

Nadat een transactie is ingediend, kun je de details ervan ophalen met behulp van de transactiehandtekening en de getTransaction RPC-methode. De respons zal een structuur hebben die vergelijkbaar is met het volgende fragment.

Je kunt de transactie ook vinden met behulp van Solana Explorer.

Transaction Data
{
"blockTime": 1745196488,
"meta": {
"computeUnitsConsumed": 150,
"err": null,
"fee": 5000,
"innerInstructions": [],
"loadedAddresses": {
"readonly": [],
"writable": []
},
"logMessages": [
"Program 11111111111111111111111111111111 invoke [1]",
"Program 11111111111111111111111111111111 success"
],
"postBalances": [989995000, 10000000, 1],
"postTokenBalances": [],
"preBalances": [1000000000, 0, 1],
"preTokenBalances": [],
"rewards": [],
"status": {
"Ok": null
}
},
"slot": 13049,
"transaction": {
"message": {
"header": {
"numReadonlySignedAccounts": 0,
"numReadonlyUnsignedAccounts": 1,
"numRequiredSignatures": 1
},
"accountKeys": [
"8PLdpLxkuv9Nt8w3XcGXvNa663LXDjSrSNon4EK7QSjQ",
"7GLg7bqgLBv1HVWXKgWAm6YoPf1LoWnyWGABbgk487Ma",
"11111111111111111111111111111111"
],
"recentBlockhash": "7ZCxc2SDhzV2bYgEQqdxTpweYJkpwshVSDtXuY7uPtjf",
"instructions": [
{
"accounts": [0, 1],
"data": "3Bxs4NN8M2Yn4TLb",
"programIdIndex": 2,
"stackHeight": null
}
],
"indexToProgramIds": {}
},
"signatures": [
"3jUKrQp1UGq5ih6FTDUUt2kkqUfoG2o4kY5T1DoVHK2tXXDLdxJSXzuJGY4JPoRivgbi45U2bc7LZfMa6C4R3szX"
]
},
"version": "legacy"
}

Is this page helpful?

Inhoudsopgave

Pagina Bewerken

Beheerd door

© 2026 Solana Foundation.
Alle rechten voorbehouden.
Blijf Verbonden