Invocación entre programas
En esta sección, el programa CRUD de la sección anterior de PDA se actualiza añadiendo Invocaciones entre programas (CPIs), una característica que permite a los programas de Solana invocarse entre sí.
Este tutorial también muestra cómo los programas pueden "firmar" por Program Derived Addresses (PDAs) cuando realizan Invocaciones entre programas.
Las instrucciones update
y delete
necesitan modificación para manejar
transferencias de SOL entre cuentas invocando el System Program.
El propósito de esta sección incluye recorrer el proceso de implementación de CPIs en un programa de Solana usando el framework Anchor, basándose en los conceptos de PDA explorados en la sección anterior. Para más detalles, consulta la página Invocación entre programas.
Como referencia, este enlace incluye el código final después de completar tanto la sección de PDA como la de CPI.
El código inicial para esta sección incluye solo la sección de PDA completada.
Actualizar la instrucción de actualización
Primero, el programa necesita un mecanismo simple de "pago por actualización"
cambiando la estructura Update
y la función update
.
Comienza actualizando el archivo lib.rs
para incluir elementos del módulo
system_program
.
use anchor_lang::system_program::{transfer, Transfer};
A continuación, actualiza la estructura Update
para incluir una nueva
cuenta llamada vault_account
. Esta cuenta, controlada por el programa, recibe
SOL de un usuario cuando actualizan su cuenta de mensaje.
#[account(mut,seeds = [b"vault", user.key().as_ref()],bump,)]pub vault_account: SystemAccount<'info>,
A continuación, añade la lógica CPI en la instrucción update
para transferir
0.001 SOL desde la cuenta del usuario a la cuenta de la bóveda.
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)?;
Reconstruye el programa.
$build
Actualiza la instrucción Delete
Ahora añade un mecanismo de "reembolso al eliminar" cambiando la estructura
Delete
y la función delete
.
Primero, actualiza la estructura Delete
para incluir el vault_account
.
Esto permite transferir cualquier SOL en el vault de vuelta al usuario cuando
cierran su cuenta de mensaje.
#[account(mut,seeds = [b"vault", user.key().as_ref()],bump,)]pub vault_account: SystemAccount<'info>,
También añade el system_program
ya que el CPI para la transferencia requiere
invocar el System Program.
pub system_program: Program<'info, System>,
A continuación, añade la lógica CPI en la instrucción delete
para transferir
SOL desde la cuenta vault de vuelta a la cuenta del usuario.
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())?;
Ten en cuenta que _ctx: Context<Delete>
cambia a
ctx: Context<Delete>
para usar el contexto en el cuerpo de la función.
Reconstruye el programa.
$build
Redesplegar el programa
Después de hacer estos cambios, redespliegua el programa actualizado. Esto asegura que el programa modificado esté disponible para pruebas. En Solana, actualizar un programa simplemente requiere desplegar el programa con el mismo ID de programa.
Asegúrate de que tu cartera de Playground tenga SOL de devnet. Obtén SOL de devnet desde el Faucet de Solana.
$deploy
Actualizar archivo de prueba
A continuación, actualiza el archivo anchor.test.ts
para incluir la nueva
cuenta vault en las instrucciones. Esto requiere derivación de la PDA del vault
e incluirla en las llamadas de instrucción de actualización y eliminación.
Derivar PDA de la bóveda
Primero, añade la derivación PDA de la bóveda:
const [vaultPda, vaultBump] = PublicKey.findProgramAddressSync([Buffer.from("vault"), wallet.publicKey.toBuffer()],program.programId);
Cambiar prueba de actualización
Luego, actualiza la instrucción de actualización para incluir el
vaultAccount
const transactionSignature = await program.methods.update(message).accounts({messageAccount: messagePda,vaultAccount: vaultPda}).rpc({ commitment: "confirmed" });
Cambiar prueba de eliminación
Luego, actualiza la instrucción de eliminación para incluir el
vaultAccount
const transactionSignature = await program.methods.delete().accounts({messageAccount: messagePda,vaultAccount: vaultPda}).rpc({ commitment: "confirmed" });
Volver a ejecutar la prueba
Después de hacer estos cambios, ejecuta las pruebas para asegurarte de que todo funciona como se espera:
$test
Luego puedes inspeccionar los enlaces de SolanaFM para ver los detalles de la transacción, donde encontrarás los CPIs para las instrucciones de transferencia dentro de las instrucciones de actualización y eliminación.
CPI de actualización
CPI de eliminación
Si encuentras algún error, puedes consultar el código final.
Próximos pasos
Felicidades por completar la guía de inicio rápido de Solana. Has adquirido experiencia práctica con conceptos clave de Solana, incluyendo:
- Obtener y leer datos de cuentas
- Construir y enviar transacciones
- Desplegar y actualizar programas de Solana
- Trabajar con Program Derived Addresses (PDAs)
- Realizar Cross-Program Invocations (CPIs)
Para profundizar tu comprensión de estos conceptos, consulta la documentación de Conceptos fundamentales que proporciona explicaciones detalladas de los temas cubiertos en esta guía.
Explora más ejemplos
Si prefieres aprender con ejemplos, consulta el Repositorio de ejemplos de programas para ver una variedad de programas de ejemplo.
Solana Playground ofrece una función conveniente que te permite importar o ver proyectos usando sus enlaces de GitHub. Por ejemplo, abre este enlace de Solana Playground para ver el proyecto Anchor de este repositorio de Github.
Haz clic en el botón Import
e introduce un nombre de proyecto para añadirlo a
tu lista de proyectos en Solana Playground. Una vez que un proyecto se importa,
todos los cambios se guardan y persisten automáticamente.
Is this page helpful?