Program Derived Address

In diesem Abschnitt lernen Sie, wie Sie ein grundlegendes Create, Read, Update, Delete (CRUD)-Programm erstellen.

Diese Anleitung demonstriert ein einfaches Programm, bei dem Benutzer eine Nachricht erstellen, aktualisieren und löschen können. Jede Nachricht existiert in einem Konto mit einer deterministischen Adresse, die vom Programm selbst abgeleitet wird (Program Derived Address oder PDA).

Diese Anleitung führt Sie durch die Erstellung und das Testen eines Solana-Programms mit dem Anchor-Framework und demonstriert dabei Program Derived Addresses (PDAs). Weitere Details finden Sie auf der Seite Program Derived Addresses.

Als Referenz können Sie den endgültigen Code nach Abschluss beider Abschnitte zu PDA und Cross-Program Invocation (CPI) einsehen.

Starter-Code

Beginnen Sie, indem Sie diesen Solana Playground-Link mit dem Starter-Code öffnen. Klicken Sie dann auf die Schaltfläche "Import", um das Programm zu Ihren Solana Playground-Projekten hinzuzufügen.

ImportImport

In der Datei lib.rs finden Sie ein Programm mit den Anweisungen create, update und delete, die in den folgenden Schritten hinzugefügt werden.

lib.rs
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 {}

Führen Sie vor Beginn build im Playground-Terminal aus, um zu überprüfen, ob das Starterprogramm erfolgreich erstellt wird.

Terminal
$
build

Nachrichtenkonto-Typ definieren

Definieren Sie zunächst die Struktur für das Nachrichtenkonto, das das Programm erstellt. Diese Struktur definiert die Daten, die in dem vom Programm erstellten Konto gespeichert werden sollen.

Aktualisieren Sie in lib.rs die Struktur MessageAccount mit Folgendem:

lib.rs
#[account]
pub struct MessageAccount {
pub user: Pubkey,
pub message: String,
pub bump: u8,
}

Erstelle das Programm erneut, indem du build im Terminal ausführst.

Terminal
$
build

Dieser Code definiert, welche Daten im Nachrichten-Konto gespeichert werden sollen. Als nächstes fügst du die Programm-Anweisungen hinzu.

Erstellen-Anweisung hinzufügen

Füge nun die create Anweisung hinzu, die das MessageAccount erstellt und initialisiert.

Beginne damit, die für die Anweisung erforderlichen Konten zu definieren, indem du die Create Struktur mit folgendem aktualisierst:

lib.rs
#[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>,
}

Fügen Sie als Nächstes die Geschäftslogik für die create Anweisung hinzu, indem Sie die create Funktion mit folgendem aktualisieren:

lib.rs
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(())
}

Baue das Programm neu.

Terminal
$
build

Anweisung zum Aktualisieren hinzufügen

Füge als Nächstes die update Anweisung hinzu, um das MessageAccount mit einer neuen Nachricht zu ändern.

Wie im vorherigen Schritt, gib zuerst die Konten an, die für die update Anweisung erforderlich sind.

Aktualisiere die Update Struktur mit Folgendem:

lib.rs
#[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>,
}

Als Nächstes füge die Logik für die update Anweisung hinzu.

lib.rs
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(())
}

Baue das Programm neu

Terminal
$
build

Lösch-Anweisung hinzufügen

Als Nächstes füge die delete Anweisung hinzu, um das MessageAccount zu schließen.

Aktualisiere die Delete Struktur mit Folgendem:

lib.rs
#[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>,
}

Als Nächstes füge die Logik für die delete Anweisung hinzu.

lib.rs
pub fn delete(_ctx: Context<Delete>) -> Result<()> {
msg!("Delete Message");
Ok(())
}

Baue das Programm neu.

Terminal
$
build

Programm deployen

Sie haben nun das grundlegende CRUD-Programm fertiggestellt. Deployen Sie das Programm, indem Sie deploy im Playground-Terminal ausführen.

In diesem Beispiel werden Sie das Programm auf dem Devnet deployen, einem Solana-Cluster für Entwicklungstests.

Die Playground-Wallet verbindet sich standardmäßig mit dem Devnet. Stellen Sie sicher, dass Ihre Playground- Wallet über Devnet SOL verfügt, um für das Programm-Deployment zu bezahlen. Holen Sie sich Devnet SOL vom Solana Faucet.

Terminal
$
deploy

Testdatei einrichten

Der Starter-Code enthält auch eine Testdatei in anchor.test.ts.

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 () => {});
});

Fügen Sie den folgenden Code innerhalb von describe(), aber vor den it() Abschnitten hinzu.

anchor.test.ts
const program = pg.program;
const wallet = pg.wallet;
const [messagePda, messageBump] = PublicKey.findProgramAddressSync(
[Buffer.from("message"), wallet.publicKey.toBuffer()],
program.programId
);

Führen Sie die Testdatei aus, indem Sie test im Playground-Terminal ausführen, um zu überprüfen, ob sie wie erwartet läuft. Die nächsten Schritte fügen die eigentlichen Tests hinzu.

Terminal
$
test

Create-Anweisung aufrufen

Aktualisiere den ersten Test mit Folgendem:

anchor.test.ts
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`
);
});

Update-Anweisung aufrufen

Aktualisieren Sie den zweiten Test mit Folgendem:

anchor.test.ts
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`
);
});

Löschanweisung aufrufen

Aktualisieren Sie den dritten Test mit folgendem:

anchor.test.ts
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`
);
});

Test ausführen

Nachdem Sie Ihre Tests vorbereitet haben, führen Sie die Testdatei mit test im Playground-Terminal aus. Dieser Befehl führt die Tests gegen das auf dem Devnet bereitgestellte Programm aus und protokolliert Links zu SolanaFM, um die Transaktionsdetails anzuzeigen.

Terminal
$
test

Überprüfe die SolanaFM-Links, um die Transaktionsdetails anzusehen.

Beachten Sie, dass in diesem Beispiel beim erneuten Ausführen des Tests die create-Anweisung fehlschlägt, da messageAccount bereits als Konto existiert. Für eine gegebene PDA kann nur ein Konto existieren.

Is this page helpful?

Inhaltsverzeichnis

Seite bearbeiten

Verwaltet von

© 2026 Solana Foundation.
Alle Rechte vorbehalten.
Verbinden Sie sich