|
@@ -1,3 +1,5 @@
|
|
|
+//! Data structures that are used to provide non-argument inputs to program endpoints
|
|
|
+
|
|
|
use crate::{Accounts, ToAccountInfos, ToAccountMetas};
|
|
|
use solana_program::account_info::AccountInfo;
|
|
|
use solana_program::instruction::AccountMeta;
|
|
@@ -5,6 +7,20 @@ use solana_program::pubkey::Pubkey;
|
|
|
use std::fmt;
|
|
|
|
|
|
/// Provides non-argument inputs to the program.
|
|
|
+///
|
|
|
+/// # Example
|
|
|
+/// ```ignore
|
|
|
+/// pub fn set_data(ctx: Context<SetData>, age: u64, other_data: u32) -> ProgramResult {
|
|
|
+/// // Set account data like this
|
|
|
+/// (*ctx.accounts.my_account).age = age;
|
|
|
+/// (*ctx.accounts.my_account).other_data = other_data;
|
|
|
+/// // or like this
|
|
|
+/// let my_account = &mut ctx.account.my_account;
|
|
|
+/// my_account.age = age;
|
|
|
+/// my_account.other_data = other_data;
|
|
|
+/// Ok(())
|
|
|
+/// }
|
|
|
+/// ```
|
|
|
pub struct Context<'a, 'b, 'c, 'info, T> {
|
|
|
/// Currently executing program id.
|
|
|
pub program_id: &'a Pubkey,
|
|
@@ -40,6 +56,104 @@ impl<'a, 'b, 'c, 'info, T: Accounts<'info>> Context<'a, 'b, 'c, 'info, T> {
|
|
|
}
|
|
|
|
|
|
/// Context specifying non-argument inputs for cross-program-invocations.
|
|
|
+///
|
|
|
+/// # Example with and without PDA signature
|
|
|
+/// ```ignore
|
|
|
+/// // Callee Program
|
|
|
+///
|
|
|
+/// use anchor_lang::prelude::*;
|
|
|
+///
|
|
|
+/// declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS");
|
|
|
+///
|
|
|
+/// #[program]
|
|
|
+/// pub mod callee {
|
|
|
+/// use super::*;
|
|
|
+/// pub fn init(ctx: Context<Init>) -> ProgramResult {
|
|
|
+/// (*ctx.accounts.data).authority = ctx.accounts.authority.key();
|
|
|
+/// Ok(())
|
|
|
+/// }
|
|
|
+///
|
|
|
+/// pub fn set_data(ctx: Context<SetData>, data: u64) -> ProgramResult {
|
|
|
+/// (*ctx.accounts.data_acc).data = data;
|
|
|
+/// Ok(())
|
|
|
+/// }
|
|
|
+/// }
|
|
|
+///
|
|
|
+/// #[account]
|
|
|
+/// #[derive(Default)]
|
|
|
+/// pub struct Data {
|
|
|
+/// data: u64,
|
|
|
+/// authority: Pubkey,
|
|
|
+/// }
|
|
|
+///
|
|
|
+/// #[derive(Accounts)]
|
|
|
+/// pub struct Init<'info> {
|
|
|
+/// #[account(init, payer = payer)]
|
|
|
+/// pub data: Account<'info, Data>,
|
|
|
+/// pub payer: Signer<'info>,
|
|
|
+/// pub authority: UncheckedAccount<'info>,
|
|
|
+/// pub system_program: Program<'info, System>
|
|
|
+/// }
|
|
|
+///
|
|
|
+/// #[derive(Accounts)]
|
|
|
+/// pub struct SetData<'info> {
|
|
|
+/// #[account(mut, has_one = authority)]
|
|
|
+/// pub data_acc: Account<'info, Data>,
|
|
|
+/// pub authority: Signer<'info>,
|
|
|
+/// }
|
|
|
+///
|
|
|
+/// // Caller Program
|
|
|
+///
|
|
|
+/// use anchor_lang::prelude::*;
|
|
|
+/// use callee::{self, program::Callee};
|
|
|
+///
|
|
|
+/// declare_id!("Sxg7dBh5VLT8S1o6BqncZCPq9nhHHukjfVd6ohQJeAk");
|
|
|
+///
|
|
|
+/// #[program]
|
|
|
+/// pub mod caller {
|
|
|
+/// use super::*;
|
|
|
+/// pub fn do_cpi(ctx: Context<DoCpi>, data: u64) -> ProgramResult {
|
|
|
+/// let callee_id = ctx.accounts.callee.to_account_info();
|
|
|
+/// let callee_accounts = callee::cpi::accounts::SetData {
|
|
|
+/// data_acc: ctx.accounts.data_acc.to_account_info(),
|
|
|
+/// authority: ctx.accounts.callee_authority.to_account_info(),
|
|
|
+/// };
|
|
|
+/// let cpi_ctx = CpiContext::new(callee_id, callee_accounts);
|
|
|
+/// callee::cpi::set_data(cpi_ctx, data)
|
|
|
+/// }
|
|
|
+///
|
|
|
+/// pub fn do_cpi_with_pda_authority(ctx: Context<DoCpiWithPDAAuthority>, bump: u8, data: u64) -> ProgramResult {
|
|
|
+/// let seeds = &[&[b"example_seed", bytemuck::bytes_of(&bump)][..]];
|
|
|
+/// let callee_id = ctx.accounts.callee.to_account_info();
|
|
|
+/// let callee_accounts = callee::cpi::accounts::SetData {
|
|
|
+/// data_acc: ctx.accounts.data_acc.to_account_info(),
|
|
|
+/// authority: ctx.accounts.callee_authority.to_account_info(),
|
|
|
+/// };
|
|
|
+/// let cpi_ctx = CpiContext::new_with_signer(callee_id, callee_accounts, seeds);
|
|
|
+/// callee::cpi::set_data(cpi_ctx, data)
|
|
|
+/// }
|
|
|
+/// }
|
|
|
+///
|
|
|
+/// // We can use "UncheckedAccount"s here because
|
|
|
+/// // the callee program does the checks.
|
|
|
+/// // We use "mut" so the autogenerated clients know
|
|
|
+/// // that this account should be mutable.
|
|
|
+/// #[derive(Accounts)]
|
|
|
+/// pub struct DoCpi<'info> {
|
|
|
+/// #[account(mut)]
|
|
|
+/// pub data_acc: UncheckedAccount<'info>,
|
|
|
+/// pub callee_authority: UncheckedAccount<'info>,
|
|
|
+/// pub callee: Program<'info, Callee>,
|
|
|
+/// }
|
|
|
+///
|
|
|
+/// #[derive(Accounts)]
|
|
|
+/// pub struct DoCpiWithPDAAuthority<'info> {
|
|
|
+/// #[account(mut)]
|
|
|
+/// pub data_acc: UncheckedAccount<'info>,
|
|
|
+/// pub callee_authority: UncheckedAccount<'info>,
|
|
|
+/// pub callee: Program<'info, Callee>,
|
|
|
+/// }
|
|
|
+/// ```
|
|
|
pub struct CpiContext<'a, 'b, 'c, 'info, T>
|
|
|
where
|
|
|
T: ToAccountMetas + ToAccountInfos<'info>,
|
|
@@ -122,6 +236,7 @@ impl<'info, T: ToAccountInfos<'info> + ToAccountMetas> ToAccountMetas
|
|
|
|
|
|
/// Context specifying non-argument inputs for cross-program-invocations
|
|
|
/// targeted at program state instructions.
|
|
|
+#[doc(hidden)]
|
|
|
#[deprecated]
|
|
|
pub struct CpiStateContext<'a, 'b, 'c, 'info, T: Accounts<'info>> {
|
|
|
state: AccountInfo<'info>,
|