Özet
Bir talimat 3 alana sahiptir: program_id (hangi programın çağrılacağı),
accounts (is_signer/is_writable bayraklarına sahip AccountMeta listesi) ve
data (programın yorumladığı veri bayt dizisi).
Talimat yapısı
Bir
Instruction
üç alandan oluşur:
program_id: Çağrılan programın ID'si.accounts: Hesap metadatası dizisidata: Talimat tarafından kullanılacak ek veri içeren bayt dizisi.
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
Talimatın program_id'si, talimatın
yürütme mantığını içeren programın genel anahtar adresidir. Runtime, talimatı
işlenmek üzere doğru programa yönlendirmek için bu alanı kullanır.
Hesap metadatası
Talimatın accounts dizisi, sıralı bir
AccountMeta
struct listesidir. Talimatın etkileşimde bulunduğu her hesap için metadata
sağlanmalıdır. Validator, hangi işlemlerin paralel çalışabileceğini belirlemek
için bu metadatayı kullanır. Farklı hesaplara yazan işlemler paralel olarak
yürütülebilir.
Aşağıdaki diyagram, tek bir talimat içeren bir işlemi göstermektedir. Talimatın
accounts dizisi iki hesap için metadata içerir.
Tek talimatlı bir işlem. Talimat, accounts dizisinde iki AccountMeta struct içerir.
Her AccountMeta üç alana sahiptir:
- pubkey: Hesabın genel anahtar adresi
- is_signer: Hesap işlemi imzalamalıysa
trueolarak ayarlanır - is_writable: Talimat hesabın verisini değiştiriyorsa
trueolarak ayarlanır
Bir talimatın hangi hesapları gerektirdiğini, hangilerinin yazılabilir, salt okunur veya işlemi imzalaması gerektiğini bilmek için, program tarafından tanımlanan talimatın uygulamasına başvurmalısınız.
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,}
Veri
Talimatın data alanı, programa hangi fonksiyonun çağrılacağını söyleyen ve o
fonksiyon için argümanları sağlayan bir bayt dizisidir. Veri tipik olarak hedef
fonksiyonu tanımlayan bir ayırt edici veya indeks bayt(lar)ı ile başlar,
ardından serileştirilmiş argümanlar gelir. Kodlama formatı her program
tarafından tanımlanır (örneğin, Borsh serileştirmesi veya özel bir düzen).
Yaygın kodlama kuralları:
- Çekirdek programlar (System, Stake, Vote): Bincode ile serileştirilmiş enum varyant indeksi ve ardından serileştirilmiş argümanlar kullanır.
- Anchor programları: 8 baytlık bir ayırt edici
(
"global:<function_name>"'nin SHA-256 hash'inin ilk 8 baytı) ve ardından Borsh ile serileştirilmiş argümanlar kullanır.
Çalışma zamanı data alanını yorumlamaz. Programın process_instruction giriş
noktasına olduğu gibi iletilir.
Derlenmiş talimat
Talimatlar bir işlem mesajına serileştirildiğinde, tüm genel anahtarları mesajın
account_keys dizisindeki kompakt tamsayı indeksleriyle değiştiren
CompiledInstruction
yapılarına dönüşürler.
Örnek: SOL transfer talimatı
Aşağıdaki örnek bir SOL transfer talimatının yapısını göstermektedir.
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));
Aşağıdaki kod, önceki kod parçacıklarının çıktısını göstermektedir. Format
SDK'lar arasında farklılık gösterecektir, ancak her talimatın aynı üç gerekli
bilgi parçasını içerdiğine dikkat edin: 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}}
Aşağıdaki örnekler, transfer talimatının manuel olarak nasıl oluşturulacağını
göstermektedir. (Expanded Instruction sekmesi, Instruction sekmesiyle
işlevsel olarak eşdeğerdir.)
Pratikte, genellikle bir Instruction'yi manuel olarak oluşturmanız gerekmez.
Çoğu program, sizin için talimatları oluşturan yardımcı fonksiyonlara sahip
istemci kütüphaneleri sağlar. Eğer bir kütüphane mevcut değilse, talimatı
manuel olarak oluşturabilirsiniz.
const transferAmount = 0.01; // 0.01 SOLconst transferInstruction = getTransferSolInstruction({source: sender,destination: recipient.address,amount: transferAmount * LAMPORTS_PER_SOL});
Is this page helpful?