Özet
Tüm gerekli imzalayıcıların orijinal işlemi zaten imzaladığı CPI'lar için
invoke kullanın. PDA imzalama gerekmez. İmzalayıcı ve yazılabilir
ayrıcalıklar çağıran programdan çağrılan programa uzanır.
PDA imzalayıcıları olmayan CPI'lar
Bir CPI PDA imzalayıcıları gerektirmediğinde,
invoke
fonksiyonu kullanılır. invoke fonksiyonu, boş bir signers_seeds
dizisi ile invoke_signed fonksiyonunu çağırır. Boş imzalayıcılar dizisi,
imzalama için hiçbir PDA'nın gerekli olmadığını gösterir.
pub fn invoke(instruction: &Instruction, account_infos: &[AccountInfo]) -> ProgramResult {invoke_signed(instruction, account_infos, &[])}
Aşağıdaki örnekler Anchor ve Native Rust kullanarak bir CPI yapar. Bir hesaptan diğerine SOL transfer eden tek bir talimat içerir.
Anchor
Aşağıdaki örnekler, bir Anchor programında CPI'ları uygulamanın iki yaklaşımını gösterir. Örnekler işlevsel olarak eşdeğerdir, ancak farklı soyutlama seviyelerini gösterir.
- Örnek 1: Anchor'ın
CpiContextve yardımcı fonksiyonunu kullanır. - Örnek 2:
solana_programcrate'indensystem_instruction::transferfonksiyonunu kullanır. - Örnek 3: CPI talimatını manuel olarak oluşturur. Bu yaklaşım, çağırmak istediğiniz talimatı oluşturmaya yardımcı olacak bir crate olmadığında kullanışlıdır.
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
Aşağıdaki örnek, Native Rust ile yazılmış bir programdan nasıl CPI yapılacağını gösterir. Bir hesaptan diğerine SOL transfer eden tek bir talimat içerir. (Test dosyası programı test etmek için LiteSVM kullanır.)
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?