Program Derived Address
Tässä osiossa opit rakentamaan perus Create, Read, Update, Delete (CRUD) -ohjelman.
Tämä opas esittelee yksinkertaisen ohjelman, jossa käyttäjät voivat luoda, päivittää ja poistaa viestin. Jokainen viesti on tallennettu tiliin, jonka osoite on deterministisesti johdettu ohjelmasta itsestään (Program Derived Address eli PDA).
Tämä opas käy läpi Solana-ohjelman rakentamisen ja testaamisen käyttäen Anchor-kehystä ja havainnollistaa Program Derived Addresses (PDA) -osoitteita. Lisätietoja löydät Program Derived Addresses -sivulta.
Voit tarkastella lopullista koodia kun olet suorittanut sekä PDA- että Cross-Program Invocation (CPI) -osiot.
Aloituskoodi
Aloita avaamalla tämä Solana Playground -linkki, joka sisältää aloituskoodin. Napsauta sitten "Import"-painiketta lisätäksesi ohjelman Solana Playground -projekteihisi.
Import
Tiedostossa lib.rs
löydät ohjelman, jossa on create
,
update
ja delete
-ohjeet lisättäväksi
seuraavissa vaiheissa.
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 {}
Ennen aloittamista, suorita build
Playground-terminaalissa
tarkistaaksesi, että aloitusohjelma kääntyy onnistuneesti.
$build
Määritä viestitityypin rakenne
Ensin määritellään rakenne viestitilille, jonka ohjelma luo. Tämä rakenne määrittelee tiedot, jotka tallennetaan ohjelman luomaan tiliin.
Päivitä lib.rs
-tiedostossa MessageAccount
-rakenne seuraavasti:
#[account]pub struct MessageAccount {pub user: Pubkey,pub message: String,pub bump: u8,}
Rakenna ohjelma uudelleen suorittamalla build
terminaalissa.
$build
Tämä koodi määrittelee, mitä tietoja viestiin liittyvään tiliin tallennetaan. Seuraavaksi lisäät ohjelman ohjeet.
Lisää Create-ohje
Lisää nyt create
-ohje, joka luo ja alustaa MessageAccount
.
Aloita määrittelemällä ohjetta varten tarvittavat tilit päivittämällä
Create
-rakenne seuraavasti:
#[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>,}
Seuraavaksi lisää liiketoimintalogiikka create
-ohjeelle päivittämällä
create
-funktio seuraavasti:
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(())}
Käännä ohjelma uudelleen.
$build
Lisää päivitysohje
Seuraavaksi lisää update
-ohje, jolla voidaan muuttaa MessageAccount
uudella
viestillä.
Kuten edellisessä vaiheessa, määrittele ensin update
-ohjeen vaatimat tilit.
Päivitä Update
-rakenne seuraavasti:
#[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>,}
Seuraavaksi lisää logiikka update
-ohjeelle.
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(())}
Rakenna ohjelma uudelleen
$build
Lisää poisto-ohje
Seuraavaksi lisää delete
ohje sulkeaksesi MessageAccount
.
Päivitä Delete
rakenne seuraavasti:
#[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>,}
Seuraavaksi lisää logiikka delete
ohjeelle.
pub fn delete(_ctx: Context<Delete>) -> Result<()> {msg!("Delete Message");Ok(())}
Käännä ohjelma uudelleen.
$build
Ohjelman käyttöönotto
Olet nyt saanut valmiiksi perustason CRUD-ohjelman. Ota ohjelma käyttöön
suorittamalla deploy
Playground-terminaalissa.
Tässä esimerkissä otat ohjelman käyttöön devnetissä, joka on Solanan kehitystestauksen klusteri.
Playground-lompakko yhdistyy oletuksena devnetiin. Varmista, että Playground-lompakossasi on devnet SOLia ohjelman käyttöönoton maksamiseen. Hanki devnet SOLia Solana Faucetista.
$deploy
Testitiedoston määrittäminen
Aloituskoodi sisältää myös testitiedoston kansiossa anchor.test.ts
.
import { PublicKey } from "@solana/web3.js";describe("pda", () => {it("Create Message Account", async () => {});it("Update Message Account", async () => {});it("Delete Message Account", async () => {});});
Lisää alla oleva koodi describe()
-tiedostoon, mutta ennen it()
-osioita.
const program = pg.program;const wallet = pg.wallet;const [messagePda, messageBump] = PublicKey.findProgramAddressSync([Buffer.from("message"), wallet.publicKey.toBuffer()],program.programId);
Suorita testitiedosto ajamalla test
Playground-terminaalissa
tarkistaaksesi, että se toimii odotetusti. Seuraavissa vaiheissa lisätään
varsinaiset testit.
$test
Kutsu Create-ohjetta
Päivitä ensimmäinen testi seuraavasti:
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`);});
Kutsu Update-ohjetta
Päivitä toinen testi seuraavasti:
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`);});
Kutsu Delete-ohjetta
Päivitä kolmas testi seuraavasti:
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`);});
Suorita testi
Kun olet valmistellut testisi, suorita testitiedosto komennolla test
Playground-terminaalissa. Tämä komento suorittaa testit devnetissä
käyttöönotettua ohjelmaa vastaan ja kirjaa linkit SolanaFM:ään, josta voit
tarkastella transaktion yksityiskohtia.
$test
Tarkastele SolanaFM-linkkejä nähdäksesi transaktion yksityiskohdat.
Huomaa, että tässä esimerkissä, jos suoritat testin uudelleen, create
-ohje
epäonnistuu, koska messageAccount
on jo olemassa tilinä. Vain yksi tili voi
olla olemassa tietylle PDA:lle.
Is this page helpful?