Hướng dẫn
Các lệnh là khối xây dựng cơ bản để tương tác với blockchain Solana. Một lệnh về cơ bản là một hàm công khai mà bất kỳ ai sử dụng mạng Solana đều có thể gọi. Mỗi lệnh được sử dụng để thực hiện một hành động cụ thể. Logic thực thi cho các lệnh được lưu trữ trên chương trình, trong đó mỗi chương trình định nghĩa tập hợp các lệnh riêng của nó. Để tương tác với mạng Solana, một hoặc nhiều lệnh được thêm vào một giao dịch và gửi đến mạng để được xử lý.
Ví dụ chuyển SOL
Sơ đồ dưới đây cho thấy cách các giao dịch và lệnh hoạt động cùng nhau để cho phép người dùng tương tác với mạng. Trong ví dụ này, SOL được chuyển từ tài khoản này sang tài khoản khác.
Metadata của tài khoản người gửi chỉ ra rằng nó phải ký cho giao dịch. (Điều này cho phép System Program khấu trừ lamport.) Cả tài khoản người gửi và người nhận đều phải có khả năng ghi, để số dư lamport của họ có thể thay đổi. Để thực thi lệnh này, ví của người gửi gửi giao dịch chứa chữ ký của nó và thông điệp chứa lệnh chuyển SOL.
Sơ đồ chuyển SOL
Sau khi giao dịch được gửi, System Program xử lý lệnh chuyển và cập nhật số dư lamport của cả hai tài khoản.
Sơ đồ quy trình chuyển SOL
Ví dụ dưới đây hiển thị mã liên quan đến các sơ đồ trên. (Xem lệnh chuyển của 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.
Lệnh
Sơ đồ mô tả một giao dịch với một lệnh, được chia thành 3 thành phần
Một
Instruction
bao gồm các thông tin sau:
program_id
: ID của chương trình được gọi.accounts
: Một mảng metadata tài khoảndata
: Một mảng byte với [dữ liệu] bổ sung để được sử dụng bởi lệnh.
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
của lệnh là địa chỉ khóa
công khai của chương trình chứa logic nghiệp vụ của lệnh.
Metadata tài khoản
Mảng accounts
của lệnh là một mảng các cấu trúc
AccountMeta
.
Metadata phải được cung cấp cho mỗi tài khoản mà lệnh tương tác với. (Điều này
cho phép giao dịch thực thi các lệnh song song, miễn là chúng không sửa đổi cùng
một tài khoản.)
Sơ đồ dưới đây mô tả một giao dịch chứa một lệnh duy nhất. Mảng accounts
của
lệnh chứa metadata cho hai tài khoản.
Một giao dịch với một lệnh. Lệnh chứa hai cấu trúc AccountMeta trong mảng accounts của nó.
Metadata tài khoản bao gồm các thông tin sau:
- pubkey: Địa chỉ khóa công khai của tài khoản
- is_signer: Đặt thành
true
nếu tài khoản phải ký giao dịch - is_writable: Đặt thành
true
nếu lệnh sửa đổi dữ liệu của tài khoản
Để biết lệnh yêu cầu những tài khoản nào, bao gồm tài khoản nào phải có thể ghi, chỉ đọc, hoặc ký giao dịch, bạn phải tham khảo triển khai của lệnh, như được định nghĩa bởi chương trình.
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,}
Dữ liệu
data
của lệnh là một mảng byte xác định lệnh nào của chương trình sẽ được gọi.
Nó cũng bao gồm bất kỳ đối số nào được yêu cầu bởi lệnh.
Ví dụ tạo lệnh
Ví dụ dưới đây cho thấy cấu trúc của một lệnh chuyển 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.
Đoạn mã dưới đây hiển thị kết quả từ các đoạn mã trước đó. Định dạng có thể khác
nhau giữa các SDK, nhưng lưu ý rằng mỗi chỉ dẫn đều chứa ba thông tin bắt buộc
giống nhau: 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}}
Các ví dụ dưới đây cho thấy cách xây dựng thủ công chỉ dẫn chuyển tiền. (Tab
Expanded Instruction
về mặt chức năng tương đương với tab Instruction
)
Trong thực tế, bạn thường không phải tự xây dựng một Instruction
thủ công.
Hầu hết các chương trình đều cung cấp thư viện khách với các hàm trợ giúp tạo
chỉ dẫn cho bạn. Nếu không có sẵn thư viện, bạn có thể tự xây dựng chỉ dẫn thủ
công.
const transferAmount = 0.01; // 0.01 SOLconst transferInstruction = getTransferSolInstruction({source: sender,destination: recipient.address,amount: transferAmount * LAMPORTS_PER_SOL});
Is this page helpful?