Invocação entre Programas
Nesta seção, o programa CRUD da seção PDA anterior é atualizado adicionando Invocações entre Programas (CPIs), um recurso que permite que programas Solana invoquem uns aos outros.
Este tutorial também mostra como os programas podem "assinar" por Endereços Derivados de Programa (PDAs) ao fazer Invocações entre Programas.
As instruções update
e delete
precisam de modificação para lidar com
transferências de SOL entre contas invocando o System Program.
O objetivo desta seção inclui percorrer o processo de implementação de CPIs em um programa Solana usando o framework Anchor, construindo sobre os conceitos de PDA explorados na seção anterior. Para mais detalhes, consulte a página Invocação entre Programas.
Para referência, este link inclui o código final após completar ambas as seções PDA e CPI.
O código inicial para esta seção inclui apenas a seção PDA completa.
Atualizar a instrução de atualização
Primeiro, o programa precisa de um mecanismo simples de "pagar para atualizar"
alterando a estrutura Update
e a função update
.
Comece atualizando o arquivo lib.rs
para trazer ao escopo itens do módulo
system_program
.
use anchor_lang::system_program::{transfer, Transfer};
Em seguida, atualize a estrutura Update
para incluir uma nova conta
chamada vault_account
. Esta conta, controlada pelo programa, recebe SOL de um
usuário quando ele atualiza sua conta de mensagem.
#[account(mut,seeds = [b"vault", user.key().as_ref()],bump,)]pub vault_account: SystemAccount<'info>,
Em seguida, adicione a lógica CPI na instrução update
para transferir 0,001
SOL da conta do usuário para a conta do cofre.
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)?;
Reconstrua o programa.
$build
Atualizar a instrução Delete
Agora adicione um mecanismo de "reembolso ao excluir" alterando a estrutura
Delete
e a função delete
.
Primeiro, atualize a estrutura Delete
para incluir o vault_account
. Isso
permite a transferência de qualquer SOL no vault de volta para o usuário quando
eles fecharem sua conta de mensagem.
#[account(mut,seeds = [b"vault", user.key().as_ref()],bump,)]pub vault_account: SystemAccount<'info>,
Também adicione o system_program
já que a CPI para a transferência requer
invocar o System Program.
pub system_program: Program<'info, System>,
Em seguida, adicione a lógica CPI na instrução delete
para transferir SOL da
conta vault de volta para a conta do usuário.
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())?;
Observe que _ctx: Context<Delete>
muda para ctx: Context<Delete>
para usar o contexto no corpo da função.
Reconstrua o programa.
$build
Reimplante o programa
Após fazer essas alterações, reimplante o programa atualizado. Isso garante que o programa modificado fique disponível para testes. Na Solana, atualizar um programa simplesmente requer implantar o programa no mesmo ID de programa.
Certifique-se de que sua carteira do Playground tenha SOL da devnet. Obtenha SOL da devnet no Solana Faucet.
$deploy
Atualize o arquivo de teste
Em seguida, atualize o arquivo anchor.test.ts
para incluir a nova conta vault
nas instruções. Isso requer derivar o PDA do vault e incluí-lo nas chamadas de
instrução de atualização e exclusão.
Derivar PDA do Vault
Primeiro, adicione a derivação do PDA do vault:
const [vaultPda, vaultBump] = PublicKey.findProgramAddressSync([Buffer.from("vault"), wallet.publicKey.toBuffer()],program.programId);
Alterar o Teste de Atualização
Em seguida, atualize a instrução de atualização para incluir o
vaultAccount
const transactionSignature = await program.methods.update(message).accounts({messageAccount: messagePda,vaultAccount: vaultPda}).rpc({ commitment: "confirmed" });
Alterar o Teste de Exclusão
Em seguida, atualize a instrução de exclusão para incluir o
vaultAccount
const transactionSignature = await program.methods.delete().accounts({messageAccount: messagePda,vaultAccount: vaultPda}).rpc({ commitment: "confirmed" });
Executar o Teste Novamente
Depois de fazer essas alterações, execute os testes para garantir que tudo funcione conforme esperado:
$test
Você pode então inspecionar os links do SolanaFM para visualizar os detalhes da transação, onde encontrará os CPIs para as instruções de transferência dentro das instruções de atualização e exclusão.
CPI de Atualização
CPI de Exclusão
Se encontrar algum erro, você pode consultar o código final.
Próximos passos
Parabéns por completar o guia de início rápido da Solana. Você adquiriu experiência prática com conceitos-chave da Solana, incluindo:
- Buscar e ler dados de contas
- Construir e enviar transações
- Implantar e atualizar programas Solana
- Trabalhar com Program Derived Addresses (PDAs)
- Fazer Cross-Program Invocations (CPIs)
Para aprofundar seu entendimento desses conceitos, confira a documentação de Conceitos Fundamentais que fornece explicações detalhadas dos tópicos abordados neste guia.
Explore mais exemplos
Se você prefere aprender por exemplos, confira o Repositório de Exemplos de Programas para uma variedade de programas de exemplo.
O Solana Playground oferece um recurso conveniente que permite importar ou visualizar projetos usando seus links do GitHub. Por exemplo, abra este link do Solana Playground para visualizar o projeto Anchor deste repositório do Github.
Clique no botão Import
e insira um nome de projeto para adicioná-lo à sua
lista de projetos no Solana Playground. Uma vez que um projeto é importado,
todas as alterações são salvas e persistidas automaticamente.
Is this page helpful?