Οδηγίες
Οι οδηγίες είναι το θεμελιώδες δομικό στοιχείο για την αλληλεπίδραση με το blockchain του Solana. Μια οδηγία είναι ουσιαστικά μια δημόσια συνάρτηση που οποιοσδήποτε χρησιμοποιεί το δίκτυο Solana μπορεί να καλέσει. Κάθε οδηγία χρησιμοποιείται για την εκτέλεση μιας συγκεκριμένης ενέργειας. Η λογική εκτέλεσης για τις οδηγίες αποθηκεύεται στα προγράμματα, όπου κάθε πρόγραμμα ορίζει το δικό του σύνολο οδηγιών. Για να αλληλεπιδράσετε με το δίκτυο Solana, μία ή περισσότερες οδηγίες προστίθενται σε μια συναλλαγή και αποστέλλονται στο δίκτυο για επεξεργασία.
Παράδειγμα μεταφοράς SOL
Το παρακάτω διάγραμμα δείχνει πώς οι συναλλαγές και οι οδηγίες συνεργάζονται για να επιτρέψουν στους χρήστες να αλληλεπιδράσουν με το δίκτυο. Σε αυτό το παράδειγμα, το SOL μεταφέρεται από έναν λογαριασμό σε έναν άλλο.
Τα μεταδεδομένα του λογαριασμού αποστολέα υποδεικνύουν ότι πρέπει να υπογράψει για τη συναλλαγή. (Αυτό επιτρέπει στο System Program να αφαιρέσει lamports.) Τόσο ο λογαριασμός αποστολέα όσο και ο λογαριασμός παραλήπτη πρέπει να είναι εγγράψιμοι, ώστε να μπορεί να αλλάξει το υπόλοιπο των lamport τους. Για να εκτελέσει αυτή την οδηγία, το πορτοφόλι του αποστολέα στέλνει τη συναλλαγή που περιέχει την υπογραφή του και το μήνυμα που περιέχει την οδηγία μεταφοράς SOL.
Διάγραμμα μεταφοράς SOL
Μετά την αποστολή της συναλλαγής, το System Program επεξεργάζεται την οδηγία μεταφοράς και ενημερώνει το υπόλοιπο lamport και των δύο λογαριασμών.
Διάγραμμα διαδικασίας μεταφοράς 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);
Console
Click to execute the code.
Οδηγίες
Διάγραμμα που απεικονίζει μια συναλλαγή με μια οδηγία, χωρισμένη στα 3 συστατικά της
Μια
Instruction
αποτελείται από τις ακόλουθες πληροφορίες:
program_id
: Το ID του προγράμματος που καλείται.accounts
: Ένας πίνακας μεταδεδομένων λογαριασμούdata
: Ένας πίνακας byte με πρόσθετα [δεδομένα] που θα χρησιμοποιηθούν από την εντολή.
Instruction struct
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>,}
Program ID
Το program_id
της εντολής είναι η
διεύθυνση δημόσιου κλειδιού του προγράμματος που περιέχει την επιχειρησιακή
λογική της εντολής.
Μεταδεδομένα λογαριασμού
Ο πίνακας accounts
της εντολής είναι ένας πίνακας από δομές
AccountMeta
.
Πρέπει να παρέχονται μεταδεδομένα για κάθε λογαριασμό με τον οποίο αλληλεπιδρά η
εντολή. (Αυτό επιτρέπει στη συναλλαγή να εκτελεί εντολές παράλληλα, εφόσον δεν
τροποποιούν τον ίδιο λογαριασμό.)
Το παρακάτω διάγραμμα απεικονίζει μια συναλλαγή που περιέχει μία μόνο εντολή. Ο
πίνακας accounts
της εντολής περιέχει μεταδεδομένα για δύο λογαριασμούς.
Μια συναλλαγή με μία εντολή. Η εντολή περιέχει δύο δομές AccountMeta στον πίνακα accounts.
Τα μεταδεδομένα λογαριασμού περιλαμβάνουν τις ακόλουθες πληροφορίες:
- pubkey: Η διεύθυνση δημόσιου κλειδιού του λογαριασμού
- is_signer: Ορίζεται σε
true
αν ο λογαριασμός πρέπει να υπογράψει τη συναλλαγή - is_writable: Ορίζεται σε
true
αν η εντολή τροποποιεί τα δεδομένα του λογαριασμού
Για να γνωρίζετε ποιους λογαριασμούς απαιτεί μια εντολή, συμπεριλαμβανομένου του ποιοι πρέπει να είναι εγγράψιμοι, μόνο για ανάγνωση ή να υπογράφουν τη συναλλαγή, πρέπει να ανατρέξετε στην υλοποίηση της εντολής, όπως ορίζεται από το πρόγραμμα.
AccountMeta
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,}
Δεδομένα
Το data
της εντολής είναι ένας πίνακας byte που καθορίζει ποια από τις εντολές
του προγράμματος θα κληθεί. Περιλαμβάνει επίσης τυχόν ορίσματα που απαιτούνται
από την εντολή.
Παράδειγμα δημιουργίας εντολής
Το παρακάτω παράδειγμα δείχνει τη δομή μιας εντολής μεταφοράς 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));
Console
Click to execute the code.
Ο παρακάτω κώδικας δείχνει την έξοδο από τα προηγούμενα αποσπάσματα κώδικα. Η
μορφή θα διαφέρει μεταξύ των SDK, αλλά παρατηρήστε ότι κάθε εντολή περιέχει τα
ίδια τρία απαραίτητα κομμάτια πληροφοριών: program_id
,
accounts
, data
.
{"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}}
Τα παρακάτω παραδείγματα δείχνουν πώς να δημιουργήσετε χειροκίνητα την εντολή
μεταφοράς. (Η καρτέλα Expanded Instruction
είναι λειτουργικά ισοδύναμη με την
καρτέλα Instruction
.)
Στην πράξη, συνήθως δεν χρειάζεται να κατασκευάσετε μια Instruction
χειροκίνητα. Τα περισσότερα προγράμματα παρέχουν βιβλιοθήκες πελάτη με
βοηθητικές συναρτήσεις που δημιουργούν τις εντολές για εσάς. Αν δεν υπάρχει
διαθέσιμη βιβλιοθήκη, μπορείτε να δημιουργήσετε χειροκίνητα την εντολή.
const transferAmount = 0.01; // 0.01 SOLconst transferInstruction = getTransferSolInstruction({source: sender,destination: recipient.address,amount: transferAmount * LAMPORTS_PER_SOL});
Is this page helpful?