Instructies zijn de fundamentele bouwsteen voor interactie met de Solana blockchain. Een instructie is in essentie een publieke functie die iedereen die het Solana netwerk gebruikt kan aanroepen. Elke instructie wordt gebruikt om een specifieke actie uit te voeren. De uitvoeringslogica voor instructies is opgeslagen in programma's, waarbij elk programma zijn eigen set instructies definieert. Om te interacteren met het Solana netwerk worden een of meer instructies toegevoegd aan een transactie en naar het netwerk gestuurd om te worden verwerkt.
SOL overdracht voorbeeld
Het onderstaande diagram laat zien hoe transacties en instructies samenwerken om gebruikers in staat te stellen met het netwerk te interacteren. In dit voorbeeld wordt SOL overgedragen van één account naar een ander.
De metadata van het verzendende account geeft aan dat het moet tekenen voor de transactie. (Dit stelt het System Program in staat om lamports af te trekken.) Zowel het verzendende als het ontvangende account moeten beschrijfbaar zijn, zodat hun lamport-saldo kan veranderen. Om deze instructie uit te voeren, stuurt de portemonnee van de verzender de transactie met zijn handtekening en het bericht dat de SOL-overdracht instructie bevat.
SOL overdracht diagram
Nadat de transactie is verzonden, verwerkt het System Program de overdracht instructie en werkt het lamport-saldo van beide accounts bij.
SOL overdracht proces diagram
Het onderstaande voorbeeld toont de code die relevant is voor de bovenstaande diagrammen. (Zie de System Program's transfer instructie.)
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);
Instructies
Diagram dat een transactie met een instructie weergeeft, opgedeeld in 3 componenten
Een
Instruction
bevat de volgende informatie:
program_id: De ID van het programma dat wordt aangeroepen.accounts: Een array van account metadatadata: Een byte-array met aanvullende [data] voor gebruik door de instructie.
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
De program_id van de instructie is
het public key-adres van het programma dat de bedrijfslogica van de instructie
bevat.
Accountmetadata
De accounts-array van de instructie is een array van
AccountMeta
structs. Voor elk account waarmee de instructie interacteert, moet metadata
worden verstrekt. (Hierdoor kunnen transacties instructies parallel uitvoeren,
zolang ze niet hetzelfde account wijzigen.)
Het onderstaande diagram toont een transactie die één instructie bevat. De
accounts-array van de instructie bevat metadata voor twee accounts.
Een transactie met één instructie. De instructie bevat twee AccountMeta structs in zijn accounts-array.
De accountmetadata bevat de volgende informatie:
- pubkey: Het public key-adres van het account
- is_signer: Ingesteld op
trueals het account de transactie moet ondertekenen - is_writable: Ingesteld op
trueals de instructie de data van het account wijzigt
Om te weten welke accounts een instructie vereist, inclusief welke beschrijfbaar, alleen-lezen of de transactie moeten ondertekenen, moet je de implementatie van de instructie raadplegen, zoals gedefinieerd door het programma.
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
De data van de instructie is een byte-array die specificeert welke instructie
van het programma moet worden aangeroepen. Het bevat ook alle argumenten die de
instructie vereist.
Voorbeeld van het maken van een instructie
Het onderstaande voorbeeld toont de structuur van een SOL-overdrachtsinstructie.
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));
De onderstaande code toont de output van de vorige codefragmenten. Het formaat
zal verschillen tussen SDK's, maar merk op dat elke instructie dezelfde drie
vereiste informatiestukken bevat: 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}}
De onderstaande voorbeelden laten zien hoe je handmatig de transfer-instructie
kunt bouwen. (Het Expanded Instruction tabblad is functioneel equivalent aan
het Instruction tabblad.)
In de praktijk hoef je meestal geen Instruction handmatig te construeren. De
meeste programma's bieden clientbibliotheken met hulpfuncties die de
instructies voor je aanmaken. Als er geen bibliotheek beschikbaar is, kun je
de instructie handmatig bouwen.
const transferAmount = 0.01; // 0.01 SOLconst transferInstruction = getTransferSolInstruction({source: sender,destination: recipient.address,amount: transferAmount * LAMPORTS_PER_SOL});
Is this page helpful?