Συναλλαγές

Για να αλληλεπιδράσετε με το δίκτυο Solana, πρέπει να στείλετε μια συναλλαγή. Μπορείτε να σκεφτείτε μια συναλλαγή ως έναν φάκελο που περιέχει αρκετές φόρμες. Κάθε φόρμα είναι μια οδηγία που λέει στο δίκτυο τι να κάνει. Η αποστολή της συναλλαγής είναι σαν να ταχυδρομείτε τον φάκελο ώστε να μπορούν να επεξεργαστούν οι φόρμες.

Το παρακάτω παράδειγμα δείχνει μια απλοποιημένη έκδοση δύο συναλλαγών. Όταν η πρώτη συναλλαγή επεξεργαστεί, θα εκτελέσει μια μόνο οδηγία. Όταν η δεύτερη συναλλαγή επεξεργαστεί, θα εκτελέσει τρεις οδηγίες με διαδοχική σειρά: πρώτα την οδηγία 1, ακολουθούμενη από την οδηγία 2, ακολουθούμενη από την οδηγία 3.

Οι συναλλαγές είναι ατομικές: Αν μια μόνο οδηγία αποτύχει, ολόκληρη η συναλλαγή θα αποτύχει και δεν θα πραγματοποιηθούν αλλαγές.

Ένα απλοποιημένο διάγραμμα που δείχνει δύο συναλλαγέςΈνα απλοποιημένο διάγραμμα που δείχνει δύο συναλλαγές

Μια Transaction αποτελείται από τις ακόλουθες πληροφορίες:

  • signatures: Ένας πίνακας από υπογραφές
  • message: Πληροφορίες συναλλαγής, συμπεριλαμβανομένης της λίστας οδηγιών προς επεξεργασία
Transaction
pub struct Transaction {
#[wasm_bindgen(skip)]
#[serde(with = "short_vec")]
pub signatures: Vec<Signature>,
#[wasm_bindgen(skip)]
pub message: Message,
}

Διάγραμμα που δείχνει τα δύο μέρη μιας συναλλαγήςΔιάγραμμα που δείχνει τα δύο μέρη μιας συναλλαγής

Οι συναλλαγές έχουν συνολικό όριο μεγέθους 1232 bytes. Αυτό το όριο περιλαμβάνει τόσο τον πίνακα signatures όσο και τη δομή message.

Αυτό το όριο προέρχεται από το μέγεθος της Μέγιστης Μονάδας Μετάδοσης (MTU) του IPv6 που είναι 1280 bytes, μείον 48 bytes για τις επικεφαλίδες δικτύου (40 bytes IPv6 + 8 bytes επικεφαλίδα).

Διάγραμμα που δείχνει τη μορφή συναλλαγής και τα όρια μεγέθουςΔιάγραμμα που δείχνει τη μορφή συναλλαγής και τα όρια μεγέθους

Υπογραφές

Ο πίνακας signatures της συναλλαγής περιέχει δομές Signature. Κάθε Signature είναι 64 bytes και δημιουργείται με την υπογραφή του Message της συναλλαγής με το ιδιωτικό κλειδί του λογαριασμού. Μια υπογραφή πρέπει να παρέχεται για κάθε λογαριασμό υπογράφοντα που περιλαμβάνεται σε οποιαδήποτε από τις οδηγίες της συναλλαγής.

Η πρώτη υπογραφή ανήκει στον λογαριασμό που θα πληρώσει το βασικό τέλος της συναλλαγής και αποτελεί την υπογραφή της συναλλαγής. Η υπογραφή της συναλλαγής μπορεί να χρησιμοποιηθεί για την αναζήτηση των λεπτομερειών της συναλλαγής στο δίκτυο.

Μήνυμα

Το message της συναλλαγής είναι μια δομή Message που περιέχει τις ακόλουθες πληροφορίες:

Για εξοικονόμηση χώρου, η συναλλαγή δεν αποθηκεύει τα δικαιώματα για κάθε λογαριασμό ξεχωριστά. Αντίθετα, τα δικαιώματα λογαριασμών καθορίζονται χρησιμοποιώντας το header και το 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>,
}

Κεφαλίδα

Το header του μηνύματος είναι μια δομή MessageHeader. Περιέχει τις ακόλουθες πληροφορίες:

  • num_required_signatures: Ο συνολικός αριθμός υπογραφών που απαιτούνται από τη συναλλαγή
  • num_readonly_signed_accounts: Ο συνολικός αριθμός λογαριασμών μόνο για ανάγνωση που απαιτούν υπογραφές
  • num_readonly_unsigned_accounts: Ο συνολικός αριθμός λογαριασμών μόνο για ανάγνωση που δεν απαιτούν υπογραφές
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,
}

Διάγραμμα που δείχνει τα τρία μέρη της κεφαλίδας μηνύματοςΔιάγραμμα που δείχνει τα τρία μέρη της κεφαλίδας μηνύματος

Διευθύνσεις λογαριασμών

Το account_keys του μηνύματος είναι ένας πίνακας διευθύνσεων λογαριασμών, που αποστέλλεται σε συμπαγή μορφή πίνακα. Το πρόθεμα του πίνακα υποδεικνύει το μήκος του. Κάθε στοιχείο στον πίνακα είναι ένα δημόσιο κλειδί, που δείχνει σε έναν λογαριασμό που χρησιμοποιείται από τις οδηγίες του. Ο πίνακας accounts_keys πρέπει να είναι πλήρης και αυστηρά ταξινομημένος, ως εξής:

  1. Υπογράφων + Εγγράψιμος
  2. Υπογράφων + Μόνο για ανάγνωση
  3. Μη υπογράφων + Εγγράψιμος
  4. Μη υπογράφων + Μόνο για ανάγνωση

Η αυστηρή ταξινόμηση επιτρέπει στον πίνακα account_keys να συνδυαστεί με τις πληροφορίες στο header του μηνύματος για τον καθορισμό των δικαιωμάτων για κάθε λογαριασμό.

Διάγραμμα που δείχνει τη σειρά του πίνακα διευθύνσεων λογαριασμώνΔιάγραμμα που δείχνει τη σειρά του πίνακα διευθύνσεων λογαριασμών

Πρόσφατο blockhash

Το recent_blockhash του μηνύματος είναι μια τιμή κατακερματισμού που λειτουργεί ως χρονική σήμανση της συναλλαγής και αποτρέπει τις διπλές συναλλαγές. Ένα blockhash λήγει μετά από 150 μπλοκ. (Ισοδύναμο με ένα λεπτό—υποθέτοντας ότι κάθε μπλοκ είναι 400ms.) Μετά τη λήξη του μπλοκ, η συναλλαγή λήγει και δεν μπορεί να επεξεργαστεί.

Η μέθοδος RPC getLatestBlockhash σας επιτρέπει να λάβετε το τρέχον blockhash και το τελευταίο ύψος μπλοκ στο οποίο το blockhash θα είναι έγκυρο.

Οδηγίες

Το instructions του μηνύματος είναι ένας πίνακας όλων των οδηγιών που πρόκειται να επεξεργαστούν, αποστέλλεται σε συμπαγή μορφή πίνακα. Το πρόθεμα του πίνακα υποδεικνύει το μήκος του. Κάθε στοιχείο στον πίνακα είναι μια δομή CompiledInstruction και περιλαμβάνει τις ακόλουθες πληροφορίες:

  1. program_id_index: Ένας δείκτης που δείχνει σε μια διεύθυνση στον πίνακα account_keys. Αυτή η τιμή υποδεικνύει τη διεύθυνση του προγράμματος που επεξεργάζεται την οδηγία.
  2. accounts: Ένας πίνακας δεικτών που δείχνουν σε διευθύνσεις στον πίνακα account_keys. Κάθε δείκτης δείχνει στη διεύθυνση ενός λογαριασμού που απαιτείται για αυτήν την οδηγία.
  3. data: Ένας πίνακας byte που καθορίζει ποια οδηγία θα επικαλεστεί στο πρόγραμμα. Περιλαμβάνει επίσης τυχόν πρόσθετα δεδομένα που απαιτούνται από την οδηγία. (Για παράδειγμα, ορίσματα συνάρτησης)
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>,
}

Συμπαγής πίνακας οδηγιώνΣυμπαγής πίνακας οδηγιών

Παράδειγμα δομής συναλλαγής

Το ακόλουθο παράδειγμα δείχνει τη δομή μιας συναλλαγής που περιέχει μια μόνο οδηγία μεταφοράς SOL.

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.

Ο παρακάτω κώδικας δείχνει την έξοδο από τα προηγούμενα αποσπάσματα κώδικα. Η μορφή διαφέρει μεταξύ των SDK, αλλά παρατηρήστε ότι κάθε οδηγία περιέχει τις ίδιες απαιτούμενες πληροφορίες.

{
"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
}
}
]
}

Μετά την υποβολή μιας συναλλαγής, μπορείτε να ανακτήσετε τις λεπτομέρειές της χρησιμοποιώντας την υπογραφή της συναλλαγής και τη μέθοδο RPC getTransaction. Η απάντηση θα έχει μια δομή παρόμοια με το ακόλουθο απόσπασμα.

Μπορείτε επίσης να βρείτε τη συναλλαγή χρησιμοποιώντας τον 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?

Πίνακας Περιεχομένων

Επεξεργασία Σελίδας

Διαχειρίζεται από

© 2025 Ίδρυμα Solana.
Με επιφύλαξη παντός δικαιώματος.