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 de 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 ficheiro 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
utilizador quando atualiza a 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 utilizador 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 de exclusão
Agora adicione um mecanismo de "reembolso ao eliminar" alterando a estrutura
Delete e a função delete.
Primeiro, atualize a estrutura Delete para incluir o vault_account. Isto
permite a transferência de qualquer SOL no cofre de volta para o utilizador
quando fecha a sua conta de mensagem.
#[account(mut,seeds = [b"vault", user.key().as_ref()],bump,)]pub vault_account: SystemAccount<'info>,
Adicione também o system_program pois o 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 utilizador.
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())?;
Note que _ctx: Context<Delete> muda para ctx: Context<Delete> para
usar o contexto no corpo da função.
Reconstrua o programa.
$build
Reimplantar o programa
Após fazer essas alterações, reimplante o programa atualizado. Isso garante que o programa modificado se torne 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
Atualizar arquivo de teste
Em seguida, atualize o ficheiro anchor.test.ts para incluir a nova conta vault
nas instruções. Isto requer derivar o PDA vault e incluí-lo nas chamadas das
instruções update e delete.
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. Depois que um projeto é importado, todas
as alterações são automaticamente salvas e persistidas.
Is this page helpful?