التعليمات هي اللبنة الأساسية للتفاعل مع بلوكتشين سولانا. التعليمة هي في الأساس دالة عامة يمكن لأي شخص يستخدم شبكة سولانا استدعاؤها. تُستخدم كل تعليمة لتنفيذ إجراء محدد. يتم تخزين منطق تنفيذ التعليمات في البرامج، حيث يحدد كل برنامج مجموعته الخاصة من التعليمات. للتفاعل مع شبكة سولانا، يتم إضافة تعليمة واحدة أو أكثر إلى معاملة وإرسالها إلى الشبكة لمعالجتها.
مثال على تحويل SOL
يوضح الرسم البياني أدناه كيف تعمل المعاملات والتعليمات معًا للسماح للمستخدمين بالتفاعل مع الشبكة. في هذا المثال، يتم تحويل SOL من حساب إلى آخر.
تشير بيانات التعريف لحساب المرسل إلى أنه يجب عليه التوقيع على المعاملة. (هذا يسمح للبرنامج النظام بخصم لامبورت.) يجب أن يكون كل من حساب المرسل والمستلم قابلين للكتابة، حتى يتمكن رصيد اللامبورت الخاص بهما من التغيير. لتنفيذ هذه التعليمة، ترسل محفظة المرسل المعاملة التي تحتوي على توقيعها والرسالة التي تحتوي على تعليمة تحويل SOL.
رسم بياني لتحويل SOL
بعد إرسال المعاملة، يقوم System Program بمعالجة تعليمة التحويل وتحديث رصيد اللامبورت لكلا الحسابين.
رسم بياني لعملية تحويل 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);
التعليمات
رسم بياني يوضح معاملة تحتوي على تعليمة، مقسمة إلى 3 مكونات
يتكون
Instruction
من المعلومات التالية:
program_id: معرّف البرنامج الذي يتم استدعاؤه.accounts: مصفوفة من بيانات الحساب الوصفيةdata: مصفوفة بايتات تحتوي على [بيانات] إضافية لاستخدامها بواسطة التعليمة.
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 الخاص بالتعليمة هو
عنوان المفتاح العام للبرنامج الذي يحتوي على منطق العمل الخاص بالتعليمة.
البيانات الوصفية للحساب
مصفوفة accounts الخاصة بالتعليمة هي مصفوفة من هياكل
AccountMeta.
يجب توفير البيانات الوصفية لكل حساب تتفاعل معه التعليمة. (يتيح هذا للمعاملة
تنفيذ التعليمات بشكل متوازٍ، طالما أنها لا تعدّل نفس الحساب.)
يوضح الرسم التخطيطي أدناه معاملة تحتوي على تعليمة واحدة. تحتوي مصفوفة accounts
الخاصة بالتعليمة على بيانات وصفية لحسابين.
معاملة تحتوي على تعليمة واحدة. تحتوي التعليمة على هيكلين من AccountMeta في مصفوفة accounts الخاصة بها.
تتضمن البيانات الوصفية للحساب المعلومات التالية:
- pubkey: عنوان المفتاح العام للحساب
- is_signer: يتم تعيينه إلى
trueإذا كان يجب على الحساب التوقيع على المعاملة - is_writable: يتم تعيينه إلى
trueإذا كانت التعليمة تعدّل بيانات الحساب
لمعرفة الحسابات التي تتطلبها التعليمة، بما في ذلك تلك التي يجب أن تكون قابلة للكتابة، أو للقراءة فقط، أو التي يجب أن توقع على المعاملة، يجب عليك الرجوع إلى تنفيذ التعليمة، كما هو محدد بواسطة البرنامج.
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 الخاصة بالتعليمة هي مصفوفة بايتات تحدد أي من تعليمات البرنامج سيتم
استدعاؤها. كما تتضمن أي معاملات مطلوبة بواسطة التعليمة.
مثال على إنشاء تعليمة
يوضح المثال أدناه بنية تعليمة تحويل 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، لكن لاحظ أن كل تعليمة تحتوي على نفس المعلومات الثلاث المطلوبة:
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?