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.

lib.rs
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.

lib.rs
#[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.

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

Reconstrua o programa.

Terminal
$
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.

lib.rs
#[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.

lib.rs
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.

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

Observe que _ctx: Context<Delete> muda para ctx: Context<Delete> para usar o contexto no corpo da função.

Reconstrua o programa.

Terminal
$
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.

Terminal
$
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:

anchor.test.ts
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

anchor.test.ts
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

anchor.test.ts
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:

Terminal
$
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çãoCPI de Atualização

CPI de ExclusãoCPI 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?

Índice

Editar Página