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
.
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.
#[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.
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.
$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.
#[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.
pub system_program: Program<'info, System>,
Successivamente, aggiungi la logica CPI nell'istruzione delete
per trasferire
SOL dall'account vault all'account dell'utente.
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.
$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.
$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:
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
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
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:
$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 aggiornamento
CPI 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?