Samenvatting
Gebruik invoke voor CPI's waarbij alle vereiste ondertekenaars de
oorspronkelijke transactie al hebben ondertekend. Er is geen PDA-ondertekening
nodig. Ondertekenaar- en schrijfrechten worden uitgebreid van de aanroeper
naar de aangeroepene.
CPI's zonder PDA-ondertekenaars
Wanneer een CPI geen PDA-ondertekenaars vereist, wordt de
invoke
functie gebruikt. De invoke functie roept de invoke_signed functie
aan met een lege signers_seeds array. De lege ondertekenaars-array geeft
aan dat er geen PDA's vereist zijn voor ondertekening.
pub fn invoke(instruction: &Instruction, account_infos: &[AccountInfo]) -> ProgramResult {invoke_signed(instruction, account_infos, &[])}
De onderstaande voorbeelden maken een CPI met Anchor en Native Rust. Het bevat een enkele instructie die SOL overdraagt van het ene account naar het andere.
Anchor
De volgende voorbeelden tonen twee benaderingen voor het implementeren van CPI's in een Anchor programma. De voorbeelden zijn functioneel equivalent, maar demonstreren verschillende abstractieniveaus.
- Voorbeeld 1: Gebruikt Anchor's
CpiContexten helperfunctie. - Voorbeeld 2: Gebruikt de
system_instruction::transferfunctie uit desolana_programcrate. - Voorbeeld 3: Construeert de CPI-instructie handmatig. Deze benadering is nuttig wanneer er geen crate bestaat om de instructie te helpen bouwen die je wilt aanroepen.
use anchor_lang::prelude::*;use anchor_lang::system_program::{transfer, Transfer};declare_id!("9AvUNHjxscdkiKQ8tUn12QCMXtcnbR9BVGq3ULNzFMRi");#[program]pub mod cpi {use super::*;pub fn sol_transfer(ctx: Context<SolTransfer>, amount: u64) -> Result<()> {let from_pubkey = ctx.accounts.sender.to_account_info();let to_pubkey = ctx.accounts.recipient.to_account_info();let program_id = ctx.accounts.system_program.to_account_info();let cpi_context = CpiContext::new(program_id,Transfer {from: from_pubkey,to: to_pubkey,},);transfer(cpi_context, amount)?;Ok(())}}#[derive(Accounts)]pub struct SolTransfer<'info> {#[account(mut)]sender: Signer<'info>,#[account(mut)]recipient: SystemAccount<'info>,system_program: Program<'info, System>,}
Rust
Het volgende voorbeeld toont hoe een CPI te maken vanuit een programma geschreven in Native Rust. Het bevat een enkele instructie die SOL overdraagt van het ene account naar het andere. (Het testbestand gebruikt LiteSVM om het programma te testen.)
use borsh::BorshDeserialize;use solana_program::{account_info::AccountInfo,entrypoint,entrypoint::ProgramResult,program::invoke,program_error::ProgramError,pubkey::Pubkey,system_instruction,};// Declare program entrypointentrypoint!(process_instruction);// Define program instructions#[derive(BorshDeserialize)]enum ProgramInstruction {SolTransfer { amount: u64 },}impl ProgramInstruction {fn unpack(input: &[u8]) -> Result<Self, ProgramError> {Self::try_from_slice(input).map_err(|_| ProgramError::InvalidInstructionData)}}pub fn process_instruction(_program_id: &Pubkey,accounts: &[AccountInfo],instruction_data: &[u8],) -> ProgramResult {// Deserialize instruction datalet instruction = ProgramInstruction::unpack(instruction_data)?;// Process instructionmatch instruction {ProgramInstruction::SolTransfer { amount } => {// Parse accountslet [sender_info, recipient_info, system_program_info] = accounts else {return Err(ProgramError::NotEnoughAccountKeys);};// Verify the sender is a signerif !sender_info.is_signer {return Err(ProgramError::MissingRequiredSignature);}// Create and invoke the transfer instructionlet transfer_ix = system_instruction::transfer(sender_info.key,recipient_info.key,amount,);invoke(&transfer_ix,&[sender_info.clone(),recipient_info.clone(),system_program_info.clone(),],)?;Ok(())}}}
Is this page helpful?