Browse Source

lang/docs: Context and CpiContext docs (#1247)

Paul 3 years ago
parent
commit
bb20eee8f6
2 changed files with 116 additions and 1 deletions
  1. 1 1
      .github/actions/setup/action.yaml
  2. 115 0
      lang/src/context.rs

+ 1 - 1
.github/actions/setup/action.yaml

@@ -3,7 +3,7 @@ description: "Setup"
 runs:
   using: "composite"
   steps:
-      - run: sudo apt-get install -y pkg-config build-essential libudev-dev
+      - run: sudo apt-get update && sudo apt-get install -y pkg-config build-essential libudev-dev
         shell: bash
       - run: echo "ANCHOR_VERSION=$(cat ./VERSION)" >> $GITHUB_ENV
         shell: bash

+ 115 - 0
lang/src/context.rs

@@ -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>,