Program Derived Address
Bu bölümde, temel bir Oluştur, Oku, Güncelle, Sil (CRUD) programı oluşturmayı öğreneceksiniz.
Bu rehber, kullanıcıların bir mesaj oluşturabileceği, güncelleyebileceği ve silebileceği basit bir programı göstermektedir. Her mesaj, programın kendisinden türetilen deterministik bir adrese sahip bir hesapta (Program Derived Address veya PDA) bulunur.
Bu rehber, Anchor framework kullanarak bir Solana programı oluşturma ve test etme sürecini, Program Derived Address (PDA) kavramını göstererek anlatmaktadır. Daha fazla ayrıntı için Program Derived Addresses sayfasına bakın.
Referans olarak, hem PDA hem de Cross Program Invocation (CPI) bölümlerini tamamladıktan sonra nihai kodu görüntüleyebilirsiniz.
Başlangıç Kodu
Başlangıç koduyla birlikte bu Solana Playground bağlantısını açarak başlayın. Ardından programı Solana Playground projelerinize eklemek için "Import" düğmesine tıklayın.
İçe Aktar
lib.rs
dosyasında, sonraki adımlarda ekleyeceğiniz create
,
update
ve delete
talimatlarını içeren bir
program bulacaksınız.
use anchor_lang::prelude::*;declare_id!("8KPzbM2Cwn4Yjak7QYAEH9wyoQh86NcBicaLuzPaejdw");#[program]pub mod pda {use super::*;pub fn create(_ctx: Context<Create>) -> Result<()> {Ok(())}pub fn update(_ctx: Context<Update>) -> Result<()> {Ok(())}pub fn delete(_ctx: Context<Delete>) -> Result<()> {Ok(())}}#[derive(Accounts)]pub struct Create {}#[derive(Accounts)]pub struct Update {}#[derive(Accounts)]pub struct Delete {}#[account]pub struct MessageAccount {}
Başlamadan önce, başlangıç programının başarıyla derlendiğini kontrol etmek için
Playground terminalinde build
komutunu çalıştırın.
$build
Mesaj Hesap Türünü Tanımlama
İlk olarak, programın oluşturacağı mesaj hesabı için yapıyı tanımlayın. Bu yapı, program tarafından oluşturulan hesapta saklanacak verileri tanımlar.
lib.rs
içinde, MessageAccount
yapısını aşağıdaki şekilde güncelleyin:
#[account]pub struct MessageAccount {pub user: Pubkey,pub message: String,pub bump: u8,}
Terminalde build
komutunu çalıştırarak programı tekrar derleyin.
$build
Bu kod, mesaj hesabında hangi verilerin saklanacağını tanımlar. Sonraki adımda, program talimatlarını ekleyeceksiniz.
Oluşturma talimatı ekle
Şimdi, MessageAccount
oluşturan ve başlatan create
talimatını
ekleyin.
Create
yapısını aşağıdakilerle güncelleyerek, talimat için gereken
hesapları tanımlamaya başlayın:
#[derive(Accounts)]#[instruction(message: String)]pub struct Create<'info> {#[account(mut)]pub user: Signer<'info>,#[account(init,seeds = [b"message", user.key().as_ref()],bump,payer = user,space = 8 + 32 + 4 + message.len() + 1)]pub message_account: Account<'info, MessageAccount>,pub system_program: Program<'info, System>,}
Ardından, create
talimatı için iş mantığını ekleyin ve create
fonksiyonunu aşağıdaki şekilde güncelleyin:
pub fn create(ctx: Context<Create>, message: String) -> Result<()> {msg!("Create Message: {}", message);let account_data = &mut ctx.accounts.message_account;account_data.user = ctx.accounts.user.key();account_data.message = message;account_data.bump = ctx.bumps.message_account;Ok(())}
Programı yeniden derleyin.
$build
Güncelleme Talimatı Ekle
Şimdi, MessageAccount
öğesini yeni bir mesajla değiştirmek için update
talimatını ekleyin.
Önceki adımda olduğu gibi, önce update
talimatı için gereken hesapları
belirtin.
Update
yapısını aşağıdaki gibi güncelleyin:
#[derive(Accounts)]#[instruction(message: String)]pub struct Update<'info> {#[account(mut)]pub user: Signer<'info>,#[account(mut,seeds = [b"message", user.key().as_ref()],bump = message_account.bump,realloc = 8 + 32 + 4 + message.len() + 1,realloc::payer = user,realloc::zero = true,)]pub message_account: Account<'info, MessageAccount>,pub system_program: Program<'info, System>,}
Şimdi, update
talimatı için mantığı ekleyin.
pub fn update(ctx: Context<Update>, message: String) -> Result<()> {msg!("Update Message: {}", message);let account_data = &mut ctx.accounts.message_account;account_data.message = message;Ok(())}
Programı yeniden derleyin
$build
Silme talimatı ekleyin
Şimdi, MessageAccount
hesabını kapatmak için delete
talimatını
ekleyin.
Delete
yapısını aşağıdaki gibi güncelleyin:
#[derive(Accounts)]pub struct Delete<'info> {#[account(mut)]pub user: Signer<'info>,#[account(mut,seeds = [b"message", user.key().as_ref()],bump = message_account.bump,close = user,)]pub message_account: Account<'info, MessageAccount>,}
Şimdi, delete
talimatı için mantığı ekleyin.
pub fn delete(_ctx: Context<Delete>) -> Result<()> {msg!("Delete Message");Ok(())}
Programı yeniden derleyin.
$build
Programı dağıtın
Artık temel CRUD programını tamamladınız. Playground terminalinde deploy
komutunu çalıştırarak programı dağıtın.
Bu örnekte, programı geliştirme testi için bir Solana kümesi olan devnet'e dağıtacaksınız.
Playground cüzdanı varsayılan olarak devnet'e bağlanır. Program dağıtımı için ödeme yapmak üzere Playground cüzdanınızda devnet SOL olduğundan emin olun. Solana Faucet adresinden devnet SOL alabilirsiniz.
$deploy
Test Dosyasını Ayarlama
Başlangıç kodu ayrıca anchor.test.ts
içinde bir test dosyası içerir.
import { PublicKey } from "@solana/web3.js";describe("pda", () => {it("Create Message Account", async () => {});it("Update Message Account", async () => {});it("Delete Message Account", async () => {});});
Aşağıdaki kodu describe()
içine, ancak it()
bölümlerinden önce
ekleyin.
const program = pg.program;const wallet = pg.wallet;const [messagePda, messageBump] = PublicKey.findProgramAddressSync([Buffer.from("message"), wallet.publicKey.toBuffer()],program.programId);
Playground terminalinde test
komutunu çalıştırarak test dosyasını
çalıştırın ve beklendiği gibi çalıştığını kontrol edin. Sonraki adımlar gerçek
testleri ekler.
$test
Create Talimatını Çağırma
İlk testi aşağıdaki şekilde güncelleyin:
it("Create Message Account", async () => {const message = "Hello, World!";const transactionSignature = await program.methods.create(message).accounts({messageAccount: messagePda}).rpc({ commitment: "confirmed" });const messageAccount = await program.account.messageAccount.fetch(messagePda,"confirmed");console.log(JSON.stringify(messageAccount, null, 2));console.log("Transaction Signature:",`https://solana.fm/tx/${transactionSignature}?cluster=devnet-solana`);});
Güncelleme Talimatını Çağır
İkinci testi aşağıdaki şekilde güncelleyin:
it("Update Message Account", async () => {const message = "Hello, Solana!";const transactionSignature = await program.methods.update(message).accounts({messageAccount: messagePda}).rpc({ commitment: "confirmed" });const messageAccount = await program.account.messageAccount.fetch(messagePda,"confirmed");console.log(JSON.stringify(messageAccount, null, 2));console.log("Transaction Signature:",`https://solana.fm/tx/${transactionSignature}?cluster=devnet-solana`);});
Silme Talimatını Çağır
Üçüncü testi aşağıdaki gibi güncelleyin:
it("Delete Message Account", async () => {const transactionSignature = await program.methods.delete().accounts({messageAccount: messagePda}).rpc({ commitment: "confirmed" });const messageAccount = await program.account.messageAccount.fetchNullable(messagePda,"confirmed");console.log("Expect Null:", JSON.stringify(messageAccount, null, 2));console.log("Transaction Signature:",`https://solana.fm/tx/${transactionSignature}?cluster=devnet-solana`);});
Testi Çalıştır
Testlerinizi hazırladıktan sonra, Playground terminalinde test
ile test
dosyasını çalıştırın. Bu komut, devnet üzerinde dağıtılan programa karşı
testleri çalıştırır ve işlem detaylarını görmek için SolanaFM bağlantılarını
kaydeder.
$test
İşlem detaylarını görmek için SolanaFM bağlantılarını inceleyin.
Bu örnekte, testi tekrar çalıştırırsanız, messageAccount
zaten bir hesap
olarak var olduğu için create
talimatı başarısız olur. Belirli bir PDA için
yalnızca bir hesap var olabilir.
Is this page helpful?