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 bulunur (Program Derived Address veya PDA).
Bu rehber, Anchor framework kullanarak bir Solana programı oluşturma ve test etme sürecinde size Program Derived Address'leri (PDA'lar) göstermektedir. 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, create
, update
ve
delete
talimatlarını içeren bir program bulacaksınız sonraki
adımlarda ekleyeceksiniz.
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>,}
Şimdi, create
fonksiyonunu aşağıdakilerle güncelleyerek create
talimatı
için iş mantığını ekleyin:
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ı Ekleme
Sonraki adımda, MessageAccount
değerini 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ını 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. Devnet SOL'u Solana Faucet adresinden alabilirsiniz.
$deploy
Test dosyasını ayarlayın
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ğırma
İ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örüntülemek için SolanaFM
bağlantılarını kaydeder.
$test
İşlem detaylarını görüntülemek için SolanaFM bağlantılarını inceleyin.
Bu örnekte, testi tekrar çalıştırırsanız, create
talimatının başarısız
olacağını unutmayın çünkü messageAccount
zaten bir hesap olarak var. Belirli
bir PDA için yalnızca bir hesap var olabilir.
Is this page helpful?