Skip to main content

The Program Module

The program module is where you define your business logic. You do so by writing functions which can be called by clients or other programs. You've already seen one example of such a function, the set_data function from the previous section.


#[program]
mod hello_anchor {
use super::*;
pub fn set_data(ctx: Context<SetData>, data: u64) -> Result<()> {
if ctx.accounts.token_account.amount > 0 {
ctx.accounts.my_account.data = data;
}
Ok(())
}
}

Context

Context Reference

Each endpoint function takes a Context type as its first argument. Through this context argument it can access the accounts (ctx.accounts), the program id (ctx.program_id) of the executing program, and the remaining accounts (ctx.remaining_accounts). remaining_accounts is a vector that contains all accounts that were passed into the instruction but are not declared in the Accounts struct. This is useful when you want your function to handle a variable amount of accounts, e.g. when initializing a game with a variable number of players.

Instruction Data

If your function requires instruction data, you can add it by adding arguments to the function after the context argument. Anchor will then automatically deserialize the instruction data into the arguments. You can have as many as you like. You can even pass in your own types as long as you use#[derive(AnchorDeserialize)] on them or implement AnchorDeserialize for them yourself. Here's an example with a custom type used as an instruction data arg:

#[program]
mod hello_anchor {
use super::*;
pub fn set_data(ctx: Context<SetData>, data: Data) -> Result<()> {
ctx.accounts.my_account.data = data.data;
ctx.accounts.my_account.age = data.age;
Ok(())
}
}

#[account]
#[derive(Default)]
pub struct MyAccount {
pub data: u64,
pub age: u8
}

#[derive(AnchorSerialize, AnchorDeserialize, Eq, PartialEq, Clone, Copy, Debug)]
pub struct Data {
pub data: u64,
pub age: u8
}

Conveniently, #[account] implements Anchor(De)Serialize for MyAccount, so the example above can be simplified.

#[program]
mod hello_anchor {
use super::*;
pub fn set_data(ctx: Context<SetData>, data: MyAccount) -> Result<()> {
ctx.accounts.my_account.set_inner(data);
Ok(())
}
}

#[account]
#[derive(Default)]
pub struct MyAccount {
pub data: u64,
pub age: u8
}