Instructies
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);
Console
Click to execute the code.
Instructies
Diagram dat een transactie met een instructie weergeeft, opgedeeld in 3 componenten
Een
Instruction
bestaat uit de volgende informatie:
program_id
: De ID van het programma dat wordt aangeroepen.accounts
: Een array van accountmetadatadata
: Een byte-array met aanvullende [data] die door de instructie wordt gebruikt.
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
De program_id
van de instructie is
het pubkey-adres van het programma dat de bedrijfslogica van de instructie
bevat.
Accountmetadata
De accounts
array van de instructie is een array van
AccountMeta
structs. Metadata moet worden verstrekt voor elk account waarmee de instructie
interactie heeft. (Dit maakt het mogelijk om transacties parallel instructies te
laten uitvoeren, zolang ze niet dezelfde 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 pubkey-adres van het account
- is_signer: Ingesteld op
true
als het account de transactie moet ondertekenen - is_writable: Ingesteld op
true
als de instructie de gegevens 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.
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
De data
van de instructie is een byte-array die specificeert welke van de
instructies van het programma moet worden aangeroepen. Het bevat ook eventuele
argumenten die door de instructie worden 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));
Console
Click to execute the code.
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
verplichte informatie-elementen 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 tonen hoe je handmatig de transfer-instructie kunt
opbouwen. (De Expanded Instruction
tab is functioneel gelijkwaardig aan de
Instruction
tab.)
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 opbouwen.
const transferAmount = 0.01; // 0.01 SOLconst transferInstruction = getTransferSolInstruction({source: sender,destination: recipient.address,amount: transferAmount * LAMPORTS_PER_SOL});
Is this page helpful?