Συναλλαγές και Οδηγίες
Στη Solana, οι χρήστες στέλνουν συναλλαγές για να αλληλεπιδράσουν με το δίκτυο. Οι συναλλαγές περιέχουν μία ή περισσότερες οδηγίες που καθορίζουν τις λειτουργίες προς επεξεργασία. Η λογική εκτέλεσης για τις οδηγίες αποθηκεύεται σε προγράμματα που έχουν αναπτυχθεί στο δίκτυο της Solana, όπου κάθε πρόγραμμα ορίζει το δικό του σύνολο οδηγιών.
Παρακάτω παρουσιάζονται βασικές λεπτομέρειες σχετικά με την επεξεργασία συναλλαγών της Solana:
- Εάν μια συναλλαγή περιλαμβάνει πολλαπλές οδηγίες, οι οδηγίες εκτελούνται με τη σειρά που προστέθηκαν στη συναλλαγή.
- Οι συναλλαγές είναι "ατομικές" - όλες οι οδηγίες πρέπει να επεξεργαστούν επιτυχώς, διαφορετικά ολόκληρη η συναλλαγή αποτυγχάνει και δεν πραγματοποιούνται αλλαγές.
Μια συναλλαγή είναι ουσιαστικά ένα αίτημα για επεξεργασία μίας ή περισσότερων εντολών. Μπορείτε να σκεφτείτε μια συναλλαγή ως έναν φάκελο που περιέχει έντυπα. Κάθε έντυπο είναι μια εντολή που λέει στο δίκτυο τι να κάνει. Η αποστολή της συναλλαγής είναι σαν να ταχυδρομείτε τον φάκελο για να επεξεργαστούν τα έντυπα.
Απλοποιημένη Συναλλαγή
Βασικά σημεία
- Οι συναλλαγές Solana περιλαμβάνουν οδηγίες που καλούν προγράμματα στο δίκτυο.
- Οι συναλλαγές είναι ατομικές - αν οποιαδήποτε οδηγία αποτύχει, ολόκληρη η συναλλαγή αποτυγχάνει και δεν πραγματοποιούνται αλλαγές.
- Οι οδηγίες σε μια συναλλαγή εκτελούνται με διαδοχική σειρά.
- Το όριο μεγέθους συναλλαγής είναι 1232 bytes.
- Κάθε οδηγία απαιτεί τρία στοιχεία πληροφοριών:
- Τη διεύθυνση του προγράμματος που θα κληθεί
- Τους λογαριασμούς από τους οποίους η οδηγία διαβάζει ή στους οποίους γράφει
- Οποιαδήποτε επιπλέον δεδομένα απαιτούνται από την οδηγία (π.χ., ορίσματα συνάρτησης)
Παράδειγμα μεταφοράς SOL
Το παρακάτω διάγραμμα αναπαριστά μια συναλλαγή με μία μόνο εντολή για τη μεταφορά SOL από έναν αποστολέα σε έναν παραλήπτη.
Στο Solana, τα "πορτοφόλια" είναι λογαριασμοί που ανήκουν στο System Program. Μόνο ο ιδιοκτήτης του προγράμματος μπορεί να αλλάξει τα δεδομένα ενός λογαριασμού, οπότε η μεταφορά SOL απαιτεί την αποστολή μιας συναλλαγής για να καλέσει το System Program.
Μεταφορά SOL
Ο λογαριασμός του αποστολέα πρέπει να υπογράψει (is_signer
) τη συναλλαγή για
να επιτρέψει στο System Program να αφαιρέσει το υπόλοιπο των lamport του. Οι
λογαριασμοί του αποστολέα και του παραλήπτη πρέπει να είναι εγγράψιμοι
(is_writable
) αφού τα υπόλοιπα των lamport τους αλλάζουν.
Μετά την αποστολή της συναλλαγής, το System Program επεξεργάζεται την εντολή μεταφοράς. Το System Program στη συνέχεια ενημερώνει τα υπόλοιπα των lamport τόσο του λογαριασμού του αποστολέα όσο και του παραλήπτη.
Διαδικασία μεταφοράς SOL
Τα παρακάτω παραδείγματα δείχνουν πώς να στείλετε μια συναλλαγή που μεταφέρει SOL από έναν λογαριασμό σε έναν άλλο. Δείτε τον πηγαίο κώδικα της εντολής μεταφοράς του System Program εδώ.
import {airdropFactory,appendTransactionMessageInstructions,createSolanaRpc,createSolanaRpcSubscriptions,createTransactionMessage,generateKeyPairSigner,getSignatureFromTransaction,lamports,pipe,sendAndConfirmTransactionFactory,setTransactionMessageFeePayerSigner,setTransactionMessageLifetimeUsingBlockhash,signTransactionMessageWithSigners} from "@solana/kit";import { getTransferSolInstruction } from "@solana-program/system";// Create a connection to clusterconst rpc = createSolanaRpc("http://localhost:8899");const rpcSubscriptions = createSolanaRpcSubscriptions("ws://localhost:8900");// Generate sender and recipient keypairsconst sender = await generateKeyPairSigner();const recipient = await generateKeyPairSigner();const LAMPORTS_PER_SOL = 1_000_000_000n;const transferAmount = lamports(LAMPORTS_PER_SOL / 100n); // 0.01 SOL// Fund sender with airdropawait airdropFactory({ rpc, rpcSubscriptions })({recipientAddress: sender.address,lamports: lamports(LAMPORTS_PER_SOL), // 1 SOLcommitment: "confirmed"});// Check balance before transferconst { value: preBalance1 } = await rpc.getBalance(sender.address).send();const { value: preBalance2 } = await rpc.getBalance(recipient.address).send();// Create a transfer instruction for transferring SOL from sender to recipientconst transferInstruction = getTransferSolInstruction({source: sender,destination: recipient.address,amount: transferAmount // 0.01 SOL in lamports});// Add the transfer instruction to a new transactionconst { value: latestBlockhash } = await rpc.getLatestBlockhash().send();const transactionMessage = pipe(createTransactionMessage({ version: 0 }),(tx) => setTransactionMessageFeePayerSigner(sender, tx),(tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),(tx) => appendTransactionMessageInstructions([transferInstruction], tx));// Send the transaction to the networkconst signedTransaction =await signTransactionMessageWithSigners(transactionMessage);await sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions })(signedTransaction,{ commitment: "confirmed" });const transactionSignature = getSignatureFromTransaction(signedTransaction);// Check balance after transferconst { value: postBalance1 } = await rpc.getBalance(sender.address).send();const { value: postBalance2 } = await rpc.getBalance(recipient.address).send();console.log("Sender prebalance:",Number(preBalance1) / Number(LAMPORTS_PER_SOL));console.log("Recipient prebalance:",Number(preBalance2) / Number(LAMPORTS_PER_SOL));console.log("Sender postbalance:",Number(postBalance1) / Number(LAMPORTS_PER_SOL));console.log("Recipient postbalance:",Number(postBalance2) / Number(LAMPORTS_PER_SOL));console.log("Transaction Signature:", transactionSignature);
Οι βιβλιοθήκες πελάτη συχνά αφαιρούν τις λεπτομέρειες για τη δημιουργία οδηγιών προγράμματος. Αν δεν υπάρχει διαθέσιμη βιβλιοθήκη, μπορείτε να δημιουργήσετε χειροκίνητα την οδηγία. Αυτό απαιτεί να γνωρίζετε τις λεπτομέρειες υλοποίησης της οδηγίας.
Τα παρακάτω παραδείγματα δείχνουν πώς να δημιουργήσετε χειροκίνητα την οδηγία
μεταφοράς. Η καρτέλα Expanded Instruction
είναι λειτουργικά ισοδύναμη με την
καρτέλα Instruction
.
const transferAmount = 0.01; // 0.01 SOLconst transferInstruction = getTransferSolInstruction({source: sender,destination: recipient.address,amount: transferAmount * LAMPORTS_PER_SOL});
Στις παρακάτω ενότητες, θα εξετάσουμε λεπτομερώς τις συναλλαγές και τις οδηγίες.
Οδηγίες
Μια εντολή στο πρόγραμμα της Solana μπορεί να θεωρηθεί ως μια δημόσια συνάρτηση που μπορεί να κληθεί από οποιονδήποτε χρησιμοποιεί το δίκτυο Solana.
Μπορείτε να σκεφτείτε ένα πρόγραμμα Solana ως έναν διακομιστή ιστού που
φιλοξενείται στο δίκτυο Solana, όπου κάθε εντολή είναι σαν ένα δημόσιο σημείο
πρόσβασης API που οι χρήστες μπορούν να καλέσουν για να εκτελέσουν συγκεκριμένες
ενέργειες. Η επίκληση μιας εντολής είναι παρόμοια με την αποστολή ενός POST
αιτήματος σε ένα σημείο πρόσβασης API, επιτρέποντας στους χρήστες να εκτελέσουν
την επιχειρησιακή λογική του προγράμματος.
Για να καλέσετε μια εντολή προγράμματος στη Solana, χρειάζεται να δημιουργήσετε
μια Instruction
με τρία στοιχεία πληροφοριών:
- Αναγνωριστικό προγράμματος: Η διεύθυνση του προγράμματος με την επιχειρησιακή λογική για την εντολή που καλείται.
- Λογαριασμοί: Η λίστα όλων των λογαριασμών από τους οποίους η εντολή διαβάζει ή στους οποίους γράφει.
- Instruction Data: Ένας πίνακας byte που καθορίζει ποια εντολή θα κληθεί στο πρόγραμμα και τυχόν απαιτούμενα ορίσματα για την εντολή.
pub struct Instruction {/// Pubkey of the program that executes this instruction.pub program_id: Pubkey,/// Metadata describing accounts that should be passed to the program.pub accounts: Vec<AccountMeta>,/// Opaque data passed to the program for its own interpretation.pub data: Vec<u8>,}
Εντολή συναλλαγής
AccountMeta
Κατά τη δημιουργία μιας Instruction
, πρέπει να παρέχετε κάθε απαιτούμενο
λογαριασμό ως
AccountMeta
.
Το AccountMeta
καθορίζει τα εξής:
- pubkey: Η διεύθυνση του λογαριασμού
- is_signer: Αν ο λογαριασμός πρέπει να υπογράψει τη συναλλαγή
- is_writable: Αν η εντολή τροποποιεί τα δεδομένα του λογαριασμού
pub struct AccountMeta {/// An account's public key.pub pubkey: Pubkey,/// True if an `Instruction` requires a `Transaction` signature matching `pubkey`.pub is_signer: bool,/// True if the account data or metadata may be mutated during program execution.pub is_writable: bool,}
Καθορίζοντας εκ των προτέρων ποιους λογαριασμούς διαβάζει ή γράφει μια εντολή, οι συναλλαγές που δεν τροποποιούν τους ίδιους λογαριασμούς μπορούν να εκτελεστούν παράλληλα.
Για να γνωρίζετε ποιους λογαριασμούς απαιτεί μια εντολή, συμπεριλαμβανομένου του ποιοι πρέπει να είναι εγγράψιμοι, μόνο για ανάγνωση ή να υπογράψουν τη συναλλαγή, πρέπει να ανατρέξετε στην υλοποίηση της εντολής όπως ορίζεται από το πρόγραμμα.
Στην πράξη, συνήθως δεν χρειάζεται να κατασκευάσετε ένα Instruction χειροκίνητα. Οι περισσότεροι προγραμματιστές εφαρμογών παρέχουν βιβλιοθήκες πελάτη με βοηθητικές συναρτήσεις που δημιουργούν τις οδηγίες για εσάς.
AccountMeta
Παράδειγμα δομής οδηγίας
Εκτελέστε τα παρακάτω παραδείγματα για να δείτε τη δομή μιας οδηγίας μεταφοράς SOL.
import { generateKeyPairSigner, lamports } from "@solana/kit";import { getTransferSolInstruction } from "@solana-program/system";// Generate sender and recipient keypairsconst sender = await generateKeyPairSigner();const recipient = await generateKeyPairSigner();// Define the amount to transferconst 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 recipientconst transferInstruction = getTransferSolInstruction({source: sender,destination: recipient.address,amount: transferAmount});console.log(JSON.stringify(transferInstruction, null, 2));
Τα παρακάτω παραδείγματα δείχνουν την έξοδο από τα προηγούμενα αποσπάσματα κώδικα. Η ακριβής μορφή διαφέρει ανάλογα με το SDK, αλλά κάθε οδηγία Solana απαιτεί τις ακόλουθες πληροφορίες:
- Program ID: Η διεύθυνση του προγράμματος που θα εκτελέσει την οδηγία.
- Accounts: Μια λίστα λογαριασμών που απαιτούνται από την οδηγία. Για κάθε λογαριασμό, η οδηγία πρέπει να καθορίζει τη διεύθυνσή του, αν πρέπει να υπογράψει τη συναλλαγή, και αν θα γίνει εγγραφή σε αυτόν.
- Data: Ένας buffer bytes που λέει στο πρόγραμμα ποια οδηγία να εκτελέσει και περιλαμβάνει τυχόν απαιτούμενα ορίσματα από την οδηγία.
{"accounts": [{"address": "Hu28vRMGWpQXN56eaE7jRiDDRRz3vCXEs7EKHRfL6bC","role": 3,"signer": {"address": "Hu28vRMGWpQXN56eaE7jRiDDRRz3vCXEs7EKHRfL6bC","keyPair": {"privateKey": {},"publicKey": {}}}},{"address": "2mBY6CTgeyJNJDzo6d2Umipw2aGUquUA7hLdFttNEj7p","role": 1}],"programAddress": "11111111111111111111111111111111","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}}
Συναλλαγές
Αφού δημιουργήσετε τις οδηγίες που θέλετε να επικαλεστείτε, το επόμενο βήμα είναι να δημιουργήσετε ένα Transaction και να προσθέσετε τις οδηγίες στη συναλλαγή. Μια συναλλαγή Solana αποτελείται από:
- Signatures: Ένας πίνακας υπογραφών από όλους τους λογαριασμούς που απαιτούνται ως υπογράφοντες για τις οδηγίες στη συναλλαγή. Μια υπογραφή δημιουργείται υπογράφοντας το message της συναλλαγής με το ιδιωτικό κλειδί του λογαριασμού.
- Message: Το μήνυμα της συναλλαγής περιλαμβάνει τη λίστα των οδηγιών που θα επεξεργαστούν ατομικά.
pub struct Transaction {#[wasm_bindgen(skip)]#[serde(with = "short_vec")]pub signatures: Vec<Signature>,#[wasm_bindgen(skip)]pub message: Message,}
Μορφή Συναλλαγής
Η δομή ενός μηνύματος συναλλαγής αποτελείται από:
- Κεφαλίδα Μηνύματος: Καθορίζει τον αριθμό των λογαριασμών υπογραφόντων και μόνο για ανάγνωση.
- Διευθύνσεις Λογαριασμών: Ένας πίνακας διευθύνσεων λογαριασμών που απαιτούνται από τις οδηγίες στη συναλλαγή.
- Πρόσφατο Blockhash: Λειτουργεί ως χρονοσφραγίδα για τη συναλλαγή.
- Οδηγίες: Ένας πίνακας οδηγιών προς εκτέλεση.
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>,}
Μέγεθος Συναλλαγής
Οι συναλλαγές Solana έχουν όριο μεγέθους 1232 bytes. Αυτό το όριο προέρχεται από το μέγεθος της Μέγιστης Μονάδας Μετάδοσης (MTU) του IPv6 που είναι 1280 bytes, μείον 48 bytes για τις κεφαλίδες δικτύου (40 bytes IPv6 + 8 bytes κεφαλίδα).
Το συνολικό μέγεθος μιας συναλλαγής (υπογραφές και μήνυμα) πρέπει να παραμένει κάτω από αυτό το όριο και περιλαμβάνει:
- Υπογραφές: 64 bytes η καθεμία
- Μήνυμα: Κεφαλίδα (3 bytes), κλειδιά λογαριασμών (32 bytes το καθένα), πρόσφατο blockhash (32 bytes), και οδηγίες
Μορφή Συναλλαγής
Κεφαλίδα Μηνύματος
Η κεφαλίδα μηνύματος καθορίζει τα δικαιώματα για τον λογαριασμό στη συναλλαγή. Λειτουργεί σε συνδυασμό με τις αυστηρά ταξινομημένες διευθύνσεις λογαριασμών για να καθορίσει ποιοι λογαριασμοί είναι υπογράφοντες και ποιοι είναι εγγράψιμοι.
- Ο αριθμός των υπογραφών που απαιτούνται για όλες τις οδηγίες στη συναλλαγή.
- Ο αριθμός των υπογεγραμμένων λογαριασμών που είναι μόνο για ανάγνωση.
- Ο αριθμός των μη υπογεγραμμένων λογαριασμών που είναι μόνο για ανάγνωση.
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,}
Κεφαλίδα Μηνύματος
Μορφή Συμπαγούς-Πίνακα
Ένας συμπαγής πίνακας σε ένα μήνυμα συναλλαγής είναι ένας πίνακας που σειριοποιείται στην ακόλουθη μορφή:
- Το μήκος του πίνακα (κωδικοποιημένο ως compact-u16)
- Τα στοιχεία του πίνακα καταχωρημένα το ένα μετά το άλλο
Μορφή συμπαγούς πίνακα
Αυτή η μορφή χρησιμοποιείται για την κωδικοποίηση των μηκών των πινάκων Διευθύνσεις Λογαριασμών και Οδηγίες στα μηνύματα συναλλαγών.
Πίνακας Διευθύνσεων Λογαριασμών
Ένα μήνυμα συναλλαγής περιέχει μια μοναδική λίστα όλων των διευθύνσεων λογαριασμών που απαιτούνται από τις οδηγίες του. Ο πίνακας ξεκινά με έναν compact-u16 αριθμό που υποδεικνύει πόσες διευθύνσεις περιέχει.
Για εξοικονόμηση χώρου, η συναλλαγή δεν αποθηκεύει δικαιώματα για κάθε
λογαριασμό ξεχωριστά. Αντίθετα, βασίζεται σε έναν συνδυασμό του MessageHeader
και μιας αυστηρής ταξινόμησης των διευθύνσεων λογαριασμών για τον καθορισμό των
δικαιωμάτων.
Οι διευθύνσεις ταξινομούνται πάντα με τον ακόλουθο τρόπο:
- Λογαριασμοί που είναι εγγράψιμοι και υπογράφοντες
- Λογαριασμοί που είναι μόνο για ανάγνωση και υπογράφοντες
- Λογαριασμοί που είναι εγγράψιμοι και όχι υπογράφοντες
- Λογαριασμοί που είναι μόνο για ανάγνωση και όχι υπογράφοντες
Το MessageHeader
παρέχει τις τιμές που χρησιμοποιούνται για τον καθορισμό του
αριθμού των λογαριασμών για κάθε ομάδα δικαιωμάτων.
Συμπαγής πίνακας διευθύνσεων λογαριασμών
Πρόσφατο Blockhash
Κάθε συναλλαγή απαιτεί ένα πρόσφατο blockhash που εξυπηρετεί δύο σκοπούς:
- Λειτουργεί ως χρονική σήμανση για το πότε δημιουργήθηκε η συναλλαγή
- Αποτρέπει τις διπλές συναλλαγές
Ένα blockhash λήγει μετά από 150 μπλοκ (περίπου 1 λεπτό υποθέτοντας χρόνους μπλοκ 400ms), μετά το οποίο η συναλλαγή θεωρείται ληγμένη και δεν μπορεί να επεξεργαστεί.
Μπορείτε να χρησιμοποιήσετε τη μέθοδο RPC
getLatestBlockhash
για να λάβετε το
τρέχον blockhash και το τελευταίο ύψος μπλοκ στο οποίο το blockhash θα είναι
έγκυρο.
Πίνακας Οδηγιών
Ένα μήνυμα συναλλαγής περιέχει έναν πίνακα οδηγιών στον τύπο CompiledInstruction. Οι οδηγίες μετατρέπονται σε αυτόν τον τύπο όταν προστίθενται σε μια συναλλαγή.
Όπως ο πίνακας διευθύνσεων λογαριασμών στο μήνυμα, ξεκινά με ένα compact-u16 μήκος ακολουθούμενο από τα δεδομένα οδηγίας. Κάθε οδηγία περιέχει:
- Δείκτης Αναγνωριστικού Προγράμματος: Ένας δείκτης που δείχνει στη διεύθυνση του προγράμματος στον πίνακα διευθύνσεων λογαριασμών. Αυτό καθορίζει το πρόγραμμα που επεξεργάζεται την εντολή.
- Δείκτες Λογαριασμών: Ένας πίνακας δεικτών που δείχνουν στις διευθύνσεις λογαριασμών που απαιτούνται για αυτήν την εντολή.
- Instruction Data: Ένας πίνακας byte που καθορίζει ποια εντολή θα εκτελεστεί στο πρόγραμμα και οποιαδήποτε πρόσθετα δεδομένα απαιτούνται από την εντολή (π.χ. ορίσματα συνάρτησης).
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 keypairsconst sender = await generateKeyPairSigner();const recipient = await generateKeyPairSigner();// Define the amount to transferconst 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 recipientconst transferInstruction = getTransferSolInstruction({source: sender,destination: recipient.address,amount: transferAmount});// Create transaction messageconst transactionMessage = pipe(createTransactionMessage({ version: 0 }),(tx) => setTransactionMessageFeePayerSigner(sender, tx),(tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),(tx) => appendTransactionMessageInstructions([transferInstruction], tx));const signedTransaction =await signTransactionMessageWithSigners(transactionMessage);// Decode the messageBytesconst compiledTransactionMessage =getCompiledTransactionMessageDecoder().decode(signedTransaction.messageBytes);console.log(JSON.stringify(compiledTransactionMessage, null, 2));
Τα ακόλουθα παραδείγματα δείχνουν την έξοδο του μηνύματος συναλλαγής από τα προηγούμενα αποσπάσματα κώδικα. Η ακριβής μορφή διαφέρει ανάλογα με το 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.
Μια "υπογραφή συναλλαγής" προσδιορίζει μοναδικά μια συναλλαγή στο Solana. Χρησιμοποιείτε αυτήν την υπογραφή για να αναζητήσετε τις λεπτομέρειες της συναλλαγής στο δίκτυο. Η υπογραφή συναλλαγής είναι απλώς η πρώτη υπογραφή στη συναλλαγή. Σημειώστε ότι η πρώτη υπογραφή είναι επίσης η υπογραφή του πληρωτή τελών συναλλαγής.
{"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?