Cross Program Invocation

In questa sezione, il programma CRUD della precedente sezione PDA viene aggiornato aggiungendo Cross Program Invocations (CPIs), una funzionalità che consente ai programmi Solana di invocarsi a vicenda.

Questo tutorial mostra anche come i programmi possono "firmare" per i Program Derived Addresses (PDAs) quando effettuano Cross Program Invocations.

Le istruzioni update e delete necessitano di modifiche per gestire i trasferimenti di SOL tra gli account invocando il System Program.

Lo scopo di questa sezione include la spiegazione del processo di implementazione delle CPIs in un programma Solana utilizzando il framework Anchor, basandosi sui concetti di PDA esplorati nella sezione precedente. Per maggiori dettagli, consulta la pagina Cross Program Invocation.

Per riferimento, questo link include il codice finale dopo aver completato sia la sezione PDA che quella CPI.

Il codice iniziale per questa sezione include solo la sezione PDA completata.

Aggiornare l'istruzione Update

Prima di tutto, il programma necessita di un semplice meccanismo "paga-per-aggiornare" modificando la struttura Update e la funzione update.

Inizia aggiornando il file lib.rs per importare gli elementi dal modulo system_program.

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

Successivamente, aggiorna la struttura Update per includere un nuovo account chiamato vault_account. Questo account, controllato dal programma, riceve SOL da un utente quando aggiorna il proprio account di messaggi.

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

Successivamente, aggiungi la logica CPI nell'istruzione update per trasferire 0,001 SOL dall'account dell'utente all'account vault.

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)?;

Ricompila il programma.

Terminal
$
build

Aggiorna l'istruzione Delete

Ora aggiungi un meccanismo di "rimborso alla cancellazione" modificando la struct Delete e la funzione delete.

Prima, aggiorna la struct Delete per includere il vault_account. Questo permette il trasferimento di qualsiasi SOL nel vault di nuovo all'utente quando chiudono il loro account messaggio.

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

Aggiungi anche il system_program poiché la CPI per il trasferimento richiede l'invocazione del System Program.

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

Successivamente, aggiungi la logica CPI nell'istruzione delete per trasferire SOL dall'account vault all'account dell'utente.

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())?;

Nota che _ctx: Context<Delete> cambia in ctx: Context<Delete> per utilizzare il contesto nel corpo della funzione.

Ricompila il programma.

Terminal
$
build

Ridistribuisci il programma

Dopo aver apportato queste modifiche, ridistribuisci il programma aggiornato. Questo assicura che il programma modificato diventi disponibile per i test. Su Solana, l'aggiornamento di un programma richiede semplicemente la distribuzione del programma con lo stesso ID programma.

Assicurati che il tuo wallet Playground abbia SOL sulla devnet. Ottieni SOL per la devnet dal Solana Faucet.

Terminal
$
deploy

Aggiorna il file di test

Successivamente, aggiorna il file anchor.test.ts per includere il nuovo account vault nelle istruzioni. Questo richiede la derivazione del PDA del vault e la sua inclusione nelle chiamate di istruzione di aggiornamento ed eliminazione.

Deriva PDA del Vault

Prima, aggiungi la derivazione del PDA del vault:

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

Modifica il Test di Aggiornamento

Poi, aggiorna l'istruzione di aggiornamento per includere il vaultAccount

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

Modifica il Test di Eliminazione

Poi, aggiorna l'istruzione di eliminazione per includere il vaultAccount

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

Riesegui il Test

Dopo aver apportato queste modifiche, esegui i test per assicurarti che tutto funzioni come previsto:

Terminal
$
test

Puoi quindi ispezionare i link di SolanaFM per visualizzare i dettagli della transazione, dove troverai i CPI per le istruzioni di trasferimento all'interno delle istruzioni di aggiornamento ed eliminazione.

CPI di aggiornamentoCPI di aggiornamento

CPI di eliminazioneCPI di eliminazione

Se riscontri errori, puoi fare riferimento al codice finale.

Prossimi passi

Congratulazioni per aver completato la guida rapida di Solana. Hai acquisito esperienza pratica con concetti chiave di Solana tra cui:

  • Recuperare e leggere dati dagli account
  • Costruire e inviare transazioni
  • Distribuire e aggiornare programmi Solana
  • Lavorare con Program Derived Addresses (PDAs)
  • Effettuare Cross-Program Invocations (CPIs)

Per approfondire la tua comprensione di questi concetti, consulta la documentazione Concetti fondamentali che fornisce spiegazioni dettagliate degli argomenti trattati in questa guida.

Esplora altri esempi

Se preferisci imparare attraverso esempi, dai un'occhiata al Repository di esempi di programmi per una varietà di programmi di esempio.

Solana Playground offre una funzionalità conveniente che ti permette di importare o visualizzare progetti utilizzando i loro link GitHub. Ad esempio, apri questo link di Solana Playground per visualizzare il progetto Anchor da questo repository Github.

Clicca sul pulsante Import e inserisci un nome per il progetto per aggiungerlo alla tua lista di progetti in Solana Playground. Una volta importato un progetto, tutte le modifiche vengono salvate e mantenute automaticamente.

Is this page helpful?

Indice

Modifica Pagina