Cross Program Invocation

W tej sekcji program CRUD z poprzedniej sekcji dotyczącej PDA zostaje zaktualizowany poprzez dodanie Cross Program Invocations (CPIs), funkcji umożliwiającej programom Solana wywoływanie siebie nawzajem.

Ten samouczek pokazuje również, jak programy mogą "podpisywać" Program Derived Addresses (PDAs) podczas wykonywania Cross Program Invocations.

Instrukcje update i delete wymagają modyfikacji, aby obsługiwać transfery SOL między kontami poprzez wywołanie System Program.

Celem tej sekcji jest przeprowadzenie przez proces implementacji CPIs w programie Solana za pomocą frameworka Anchor, opierając się na koncepcjach PDA omówionych w poprzedniej sekcji. Więcej szczegółów znajdziesz na stronie Cross Program Invocation.

Dla odniesienia, ten link zawiera kod końcowy po ukończeniu zarówno sekcji PDA, jak i CPI.

Kod początkowy dla tej sekcji zawiera tylko ukończoną sekcję PDA.

Zaktualizuj instrukcję Update

Najpierw program potrzebuje prostego mechanizmu "pay-to-update" poprzez zmianę Update struktury i funkcji update.

Rozpocznij od aktualizacji pliku lib.rs, aby uwzględnić elementy z modułu system_program.

lib.rs
use anchor_lang::system_program::{transfer, Transfer};

Następnie zaktualizuj strukturę Update, aby uwzględnić nowe konto o nazwie vault_account. To konto, kontrolowane przez program, otrzymuje SOL od użytkownika, gdy aktualizuje on swoje konto wiadomości.

lib.rs
#[account(
mut,
seeds = [b"vault", user.key().as_ref()],
bump,
)]
pub vault_account: SystemAccount<'info>,

Następnie dodaj logikę CPI w instrukcji update, aby przelać 0,001 SOL z konta użytkownika na konto skarbca.

lib.rs
let transfer_accounts = Transfer {
from: ctx.accounts.user.to_account_info(),
to: ctx.accounts.vault_account.to_account_info(),
};
let cpi_context = CpiContext::new(
ctx.accounts.system_program.to_account_info(),
transfer_accounts,
);
transfer(cpi_context, 1_000_000)?;

Przebuduj program.

Terminal
$
build

Zaktualizuj instrukcję usuwania

Dodaj teraz mechanizm "zwrotu przy usunięciu" poprzez zmianę struktury Delete i funkcji delete.

Najpierw zaktualizuj strukturę Delete, aby uwzględniała vault_account. To pozwala na transfer dowolnych SOL w skarbcu z powrotem do użytkownika, gdy zamykają swoje konto wiadomości.

lib.rs
#[account(
mut,
seeds = [b"vault", user.key().as_ref()],
bump,
)]
pub vault_account: SystemAccount<'info>,

Dodaj również system_program, ponieważ CPI dla transferu wymaga wywołania System Programu.

lib.rs
pub system_program: Program<'info, System>,

Następnie dodaj logikę CPI w instrukcji delete, aby przelać SOL z konta skarbca z powrotem na konto użytkownika.

lib.rs
let user_key = ctx.accounts.user.key();
let signer_seeds: &[&[&[u8]]] =
&[&[b"vault", user_key.as_ref(), &[ctx.bumps.vault_account]]];
let transfer_accounts = Transfer {
from: ctx.accounts.vault_account.to_account_info(),
to: ctx.accounts.user.to_account_info(),
};
let cpi_context = CpiContext::new(
ctx.accounts.system_program.to_account_info(),
transfer_accounts,
).with_signer(signer_seeds);
transfer(cpi_context, ctx.accounts.vault_account.lamports())?;

Zauważ, że _ctx: Context<Delete> zmienia się na ctx: Context<Delete>, aby użyć kontekstu w ciele funkcji.

Przebuduj program.

Terminal
$
build

Ponowne wdrożenie programu

Po wprowadzeniu tych zmian ponownie wdroż zaktualizowany program. To zapewnia, że zmodyfikowany program będzie dostępny do testowania. Na Solanie aktualizacja programu wymaga jedynie wdrożenia programu pod tym samym ID programu.

Upewnij się, że Twój portfel Playground ma devnet SOL. Zdobądź devnet SOL z Solana Faucet.

Terminal
$
deploy

Zaktualizuj plik testowy

Następnie zaktualizuj plik anchor.test.ts, aby uwzględnić nowe konto skarbca w instrukcjach. Wymaga to wyprowadzenia PDA skarbca i uwzględnienia go w wywołaniach instrukcji aktualizacji i usunięcia.

Wyprowadź Vault PDA

Najpierw dodaj wyprowadzenie Vault PDA:

anchor.test.ts
const [vaultPda, vaultBump] = PublicKey.findProgramAddressSync(
[Buffer.from("vault"), wallet.publicKey.toBuffer()],
program.programId
);

Zmień test aktualizacji

Następnie zaktualizuj instrukcję aktualizacji, aby uwzględniała vaultAccount

anchor.test.ts
const transactionSignature = await program.methods
.update(message)
.accounts({
messageAccount: messagePda,
vaultAccount: vaultPda
})
.rpc({ commitment: "confirmed" });

Zmień test usuwania

Następnie zaktualizuj instrukcję usuwania, aby uwzględniała vaultAccount

anchor.test.ts
const transactionSignature = await program.methods
.delete()
.accounts({
messageAccount: messagePda,
vaultAccount: vaultPda
})
.rpc({ commitment: "confirmed" });

Uruchom test ponownie

Po wprowadzeniu tych zmian uruchom testy, aby upewnić się, że wszystko działa zgodnie z oczekiwaniami:

Terminal
$
test

Możesz następnie sprawdzić linki SolanaFM, aby zobaczyć szczegóły transakcji, gdzie znajdziesz CPI dla instrukcji transferu w ramach instrukcji aktualizacji i usuwania.

Aktualizacja CPIAktualizacja CPI

Usunięcie CPIUsunięcie CPI

Jeśli napotkasz jakiekolwiek błędy, możesz odwołać się do ostatecznego kodu.

Kolejne kroki

Gratulacje z ukończenia przewodnika Solana Quickstart. Zdobyłeś praktyczne doświadczenie z kluczowymi pojęciami Solana, w tym:

  • Pobieranie i odczytywanie danych z kont
  • Tworzenie i wysyłanie transakcji
  • Wdrażanie i aktualizowanie programów Solana
  • Praca z adresami pochodnymi programu (PDAs)
  • Wykonywanie wywołań międzyprogramowych (CPIs)

Aby pogłębić swoją wiedzę na temat tych pojęć, zapoznaj się z dokumentacją Podstawowe pojęcia, która zawiera szczegółowe wyjaśnienia tematów omówionych w tym przewodniku.

Odkryj więcej przykładów

Jeśli wolisz uczyć się na przykładach, sprawdź Repozytorium przykładów programów zawierające różnorodne przykłady programów.

Solana Playground oferuje wygodną funkcję umożliwiającą importowanie lub przeglądanie projektów za pomocą ich linków GitHub. Na przykład otwórz ten link do Solana Playground, aby zobaczyć projekt Anchor z tego repozytorium GitHub.

Kliknij przycisk Import i wprowadź nazwę projektu, aby dodać go do swojej listy projektów w Solana Playground. Po zaimportowaniu projektu wszystkie zmiany są automatycznie zapisywane i przechowywane.

Is this page helpful?

Spis treści

Edytuj stronę