Solana ağıyla etkileşim kurmak için bir işlem göndermeniz gerekir. Bir işlemi, içinde birkaç form bulunan bir zarf olarak düşünebilirsiniz. Her form, ağa ne yapması gerektiğini söyleyen bir talimattır. İşlemi göndermek, formların işlenebilmesi için zarfı postalamak gibidir.
Aşağıdaki örnek, iki işlemin basitleştirilmiş bir versiyonunu göstermektedir. İlk işlem işlendiğinde, tek bir talimatı yürütecektir. İkinci işlem işlendiğinde, sıralı olarak üç talimatı yürütecektir: önce talimat 1, ardından talimat 2, ardından talimat 3.
İşlemler atomiktir: Tek bir talimat başarısız olursa, tüm işlem başarısız olur ve hiçbir değişiklik gerçekleşmez.
İki işlemi gösteren basitleştirilmiş bir diyagram
Bir
Transaction
aşağıdaki bilgilerden oluşur:
signatures: İmzalar dizisimessage: İşlenecek talimatların listesi de dahil olmak üzere işlem bilgileri
pub struct Transaction {#[wasm_bindgen(skip)]#[serde(with = "short_vec")]pub signatures: Vec<Signature>,#[wasm_bindgen(skip)]pub message: Message,}
Bir işlemin iki parçasını gösteren diyagram
İşlemlerin toplam boyut sınırı
1232
bayttır. Bu sınır hem signatures dizisini hem de
message yapısını içerir.
Bu sınır, tipik internet altyapısında paket parçalanmasını önlemek için tasarlanmıştır. IPv6, 9000 bayttan daha büyük MTU'ları desteklese de, çoğu internet yönlendiricisi varsayılan olarak 1500 bayt MTU (standart Ethernet) kullanır. İşlemlerin parçalanma olmadan tek bir paket içinde sığmasını sağlamak için Solana, 1280 bayt (IPv6 için gereken minimum MTU) eksi 48 bayt ağ başlıkları (40 bayt IPv6 + 8 bayt parça/UDP başlığı) kullanır, bu da 1232 baytlık işlem boyutu sınırıyla sonuçlanır.
İşlem formatını ve boyut sınırlarını gösteren diyagram
İmzalar
İşlemin signatures dizisi Signature yapılarını içerir. Her
Signature
64 bayttır ve işlemin Message değeri hesabın özel anahtarıyla imzalanarak
oluşturulur. İşlemin talimatlarında yer alan her
imzalayan hesap için bir imza sağlanmalıdır.
İlk imza, işlemin temel ücretini ödeyecek hesaba aittir ve işlem imzasıdır. İşlem imzası, ağ üzerinde işlemin ayrıntılarını aramak için kullanılabilir.
Mesaj
İşlemin message değeri, aşağıdaki bilgileri içeren bir
Message
yapısıdır:
header: Mesaj başlığıaccount_keys: İşlemin talimatları için gerekli hesap adresleri dizisirecent_blockhash: İşlem için zaman damgası görevi gören bir blok hash'iinstructions: Talimatlar dizisi
Yer tasarrufu için işlem, her hesabın izinlerini ayrı ayrı saklamaz. Bunun
yerine, hesap izinleri header ve account_keys kullanılarak belirlenir.
pub struct Message {/// The message header, identifying signed and read-only `account_keys`.pub header: MessageHeader,/// All the account keys used by this transaction.#[serde(with = "short_vec")]pub account_keys: Vec<Pubkey>,/// The id of a recent ledger entry.pub recent_blockhash: Hash,/// Programs that will be executed in sequence and committed in/// one atomic transaction if all succeed.#[serde(with = "short_vec")]pub instructions: Vec<CompiledInstruction>,}
Başlık
Mesajın header değeri bir
MessageHeader
yapısıdır. Aşağıdaki bilgileri içerir:
num_required_signatures: İşlem için gereken toplam imza sayısınum_readonly_signed_accounts: İmza gerektiren toplam salt okunur hesap sayısınum_readonly_unsigned_accounts: İmza gerektirmeyen toplam salt okunur hesap sayısı
pub struct MessageHeader {/// The number of signatures required for this message to be considered/// valid. The signers of those signatures must match the first/// `num_required_signatures` of [`Message::account_keys`].pub num_required_signatures: u8,/// The last `num_readonly_signed_accounts` of the signed keys are read-only/// accounts.pub num_readonly_signed_accounts: u8,/// The last `num_readonly_unsigned_accounts` of the unsigned keys are/// read-only accounts.pub num_readonly_unsigned_accounts: u8,}
Mesaj başlığının üç bölümünü gösteren diyagram
Hesap adresleri
Mesajın
account_keys
değeri,
kompakt dizi formatında
gönderilen hesap adresleri dizisidir. Dizinin öneki uzunluğunu belirtir.
Dizideki her öğe, talimatları tarafından kullanılan bir hesaba işaret eden bir
genel anahtardır. accounts_keys dizisi eksiksiz ve aşağıdaki gibi kesin bir
sırayla düzenlenmiş olmalıdır:
- İmzalayan + Yazılabilir
- İmzalayan + Salt okunur
- İmzalamayan + Yazılabilir
- İmzalamayan + Salt okunur
Kesin sıralama, account_keys dizisinin mesajın header
bölümündeki bilgilerle birleştirilerek her hesap için izinlerin belirlenmesini
sağlar.
Hesap adresleri dizisinin sırasını gösteren diyagram
Son blok hash değeri
Mesajın recent_blockhash değeri, işlem zaman damgası görevi gören ve yinelenen
işlemleri önleyen bir hash değeridir. Bir blockhash
150 blok
sonra sona erer. (Her bloğun 400ms olduğu varsayıldığında bir dakikaya eşittir.)
Blok sona erdikten sonra işlem geçersiz hale gelir ve işlenemez.
getLatestBlockhash RPC metodu, mevcut
blockhash değerini ve blockhash'in geçerli olacağı son blok yüksekliğini
almanızı sağlar.
Talimatlar
Mesajın
instructions
değeri, işlenecek tüm talimatların
kompakt dizi formatında
gönderilen dizisidir. Dizinin öneki uzunluğunu belirtir. Dizideki her öğe bir
CompiledInstruction
yapısıdır ve aşağıdaki bilgileri içerir:
program_id_index:account_keysdizisindeki bir adrese işaret eden indeks. Bu değer, talimatı işleyen programın adresini belirtir.accounts:account_keysdizisindeki adreslere işaret eden indeksler dizisi. Her indeks, bu talimat için gerekli bir hesabın adresine işaret eder.data: Program üzerinde hangi talimatın çağrılacağını belirten bayt dizisi. Ayrıca talimat için gerekli ek verileri de içerir. (Örneğin, fonksiyon argümanları)
pub struct CompiledInstruction {/// Index into the transaction keys array indicating the program account that executes this instruction.pub program_id_index: u8,/// Ordered indices into the transaction keys array indicating which accounts to pass to the program.#[serde(with = "short_vec")]pub accounts: Vec<u8>,/// The program input data.#[serde(with = "short_vec")]pub data: Vec<u8>,}
Talimatların kompakt dizisi
Örnek işlem yapısı
Aşağıdaki örnek, tek bir SOL transfer talimatı içeren bir işlemin yapısını göstermektedir.
import {createSolanaRpc,generateKeyPairSigner,lamports,createTransactionMessage,setTransactionMessageFeePayerSigner,setTransactionMessageLifetimeUsingBlockhash,appendTransactionMessageInstructions,pipe,signTransactionMessageWithSigners,getCompiledTransactionMessageDecoder} from "@solana/kit";import { getTransferSolInstruction } from "@solana-program/system";const rpc = createSolanaRpc("http://localhost:8899");const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();// 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});// Create transaction messageconst transactionMessage = pipe(createTransactionMessage({ version: 0 }),(tx) => setTransactionMessageFeePayerSigner(sender, tx),(tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),(tx) => appendTransactionMessageInstructions([transferInstruction], tx));const signedTransaction =await signTransactionMessageWithSigners(transactionMessage);// Decode the messageBytesconst compiledTransactionMessage =getCompiledTransactionMessageDecoder().decode(signedTransaction.messageBytes);console.log(JSON.stringify(compiledTransactionMessage, null, 2));
Aşağıdaki kod, önceki kod parçacıklarından elde edilen çıktıyı göstermektedir. Format SDK'lar arasında farklılık gösterir, ancak her talimatın aynı gerekli bilgileri içerdiğine dikkat edin.
{"version": 0,"header": {"numSignerAccounts": 1,"numReadonlySignerAccounts": 0,"numReadonlyNonSignerAccounts": 1},"staticAccounts": ["HoCy8p5xxDDYTYWEbQZasEjVNM5rxvidx8AfyqA4ywBa","5T388jBjovy7d8mQ3emHxMDTbUF8b7nWvAnSiP3EAdFL","11111111111111111111111111111111"],"lifetimeToken": "EGCWPUEXhqHJWYBfDirq3mHZb4qDpATmYqBZMBy9TBC1","instructions": [{"programAddressIndex": 2,"accountIndices": [0, 1],"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}}]}
Bir işlem gönderildikten sonra, işlem imzasını ve getTransaction RPC yöntemini kullanarak ayrıntılarını alabilirsiniz. Yanıt, aşağıdaki kod parçasına benzer bir yapıya sahip olacaktır.
İşlemi Solana Explorer kullanarak da bulabilirsiniz.
{"blockTime": 1745196488,"meta": {"computeUnitsConsumed": 150,"err": null,"fee": 5000,"innerInstructions": [],"loadedAddresses": {"readonly": [],"writable": []},"logMessages": ["Program 11111111111111111111111111111111 invoke [1]","Program 11111111111111111111111111111111 success"],"postBalances": [989995000, 10000000, 1],"postTokenBalances": [],"preBalances": [1000000000, 0, 1],"preTokenBalances": [],"rewards": [],"status": {"Ok": null}},"slot": 13049,"transaction": {"message": {"header": {"numReadonlySignedAccounts": 0,"numReadonlyUnsignedAccounts": 1,"numRequiredSignatures": 1},"accountKeys": ["8PLdpLxkuv9Nt8w3XcGXvNa663LXDjSrSNon4EK7QSjQ","7GLg7bqgLBv1HVWXKgWAm6YoPf1LoWnyWGABbgk487Ma","11111111111111111111111111111111"],"recentBlockhash": "7ZCxc2SDhzV2bYgEQqdxTpweYJkpwshVSDtXuY7uPtjf","instructions": [{"accounts": [0, 1],"data": "3Bxs4NN8M2Yn4TLb","programIdIndex": 2,"stackHeight": null}],"indexToProgramIds": {}},"signatures": ["3jUKrQp1UGq5ih6FTDUUt2kkqUfoG2o4kY5T1DoVHK2tXXDLdxJSXzuJGY4JPoRivgbi45U2bc7LZfMa6C4R3szX"]},"version": "legacy"}
Is this page helpful?