triggr/instructions/
create_task.rs

1pub use crate::state::*;
2use anchor_lang::{prelude::*, system_program::System};
3
4// Only an account which authority is specified correctly can be used to derive the authority
5// the authority is not stored in the parent account but it's linked by derivation.
6// The authority is the payer of initializing the parent account
7
8#[derive(Accounts)]
9#[instruction(task_args: Task, _trigger_index: u64)]
10pub struct CreateTask<'info> {
11    #[account(mut)]
12    signer: Signer<'info>,
13
14    #[account(
15        mut,
16        seeds = ["user".as_bytes(), &signer.key().to_bytes()], 
17        bump
18        )]
19    user: Account<'info, User>,
20
21    #[account(
22        mut,
23        seeds = ["trigger".as_bytes(), &signer.key().to_bytes()[..], &_trigger_index.to_le_bytes()], 
24        bump 
25    )]
26    trigger: Account<'info, Trigger>,
27
28    #[account(
29        init,
30        seeds = ["task".as_bytes(), &trigger.key().to_bytes()[..], &trigger.task_count.to_le_bytes()], 
31        bump , 
32        space = task_args.try_to_vec()?.len() + 8 + 2 + 32 , 
33        payer = signer
34    )]
35    task: Account<'info, Task>,
36
37    system_program: Program<'info, System>,
38}
39
40pub fn handler(
41    ctx: Context<CreateTask>,
42    task_args: Task,
43    _trigger_index: u64,
44) -> Result<()> {
45    *ctx.accounts.task = Task::new(
46        &task_args,
47        ctx.accounts.trigger.task_count,
48        &ctx.accounts.trigger.key(),
49    )?;
50
51    // increment the trigger's task count
52    ctx.accounts.trigger.task_count += 1;
53
54    ctx.accounts.user.task_count += 1;
55
56    msg!("Task created successfully!");
57
58    Ok(())
59}
60
61// This is how to create children accounts with pdas as signer / payers
62
63// #[derive(Accounts)]
64// pub struct CreateTask<'info> {
65//     #[account()]
66//     authority: SystemAccount<'info>,
67
68//     // Should the user pay for the init of the child or should their parent pda pay?
69//     // When the user inits an task pda a simulation should estimate a certain amount of executions and ask the user to fund the account with that amount
70//     #[account(mut, seeds = ["payer".as_bytes(), &authority.key().to_bytes()], bump)]
71//     payer_pda: SystemAccount<'info>,
72
73//     #[account(mut, seeds = ["trigger".as_bytes(), &authority.key().to_bytes()], bump)]
74//     trigger: Account<'info, Trigger>,
75
76//     // Create Task and Create Trigger should be different instructions as pdas are derived differently
77//     /// CHECK: Account isn't initialized so anchor would throw error, although anchor does check the seeds
78//     #[account(mut, seeds = ["task".as_bytes(), &trigger.key().to_bytes()], bump )]
79//     task: AccountInfo<'info>,
80
81//     system_program: Program<'info, System>,
82// }
83
84// pub fn handler(ctx: Context<CreateTask>, task: Task) -> Result<()> {
85//     let payer_seeds = &[
86//         "payer".as_bytes(),
87//         &ctx.accounts.authority.key().to_bytes()[..],
88//         &[ctx.bumps.get("payer_pda").unwrap().clone()],
89//     ];
90
91//     let new_pda_seeds = &[
92//         "task".as_bytes(),
93//         &ctx.accounts.payer_pda.key().to_bytes()[..],
94//         &[ctx.bumps.get("new_pda").unwrap().clone()],
95//     ];
96
97//     // Parent and child need to sign for the initialization of the child
98//     let payer = &[&payer_seeds[..], &new_pda_seeds[..]];
99
100//     // Setup tx accounts
101//     let accounts = CreateAccount {
102//         from: ctx.accounts.payer_pda.to_account_info(),
103//         to: ctx.accounts.task.to_account_info().clone(),
104//     };
105
106//     let cpi_ctx = CpiContext::new_with_signer(
107//         ctx.accounts.system_program.to_account_info(),
108//         accounts,
109//         payer,
110//     );
111
112//     // Space is important. If you give it too liexpiration_slote space anchor will give you an invalid discriminator error regardless of what the error might be
113//     let space = task.try_to_vec().unwrap().len();
114//     let rent = Rent::get()?.minimum_balance(space);
115
116//     let mut discriminator = Task::discriminator();
117//     msg!("Discriminator: {:?}", discriminator);
118
119//     // Initializes account
120//     anchor_lang::system_program::create_account(cpi_ctx, rent, space as u64, &ctx.program_id)?;
121
122//     // Adding the discriminator allows you to use the account with regular anchor with it's proper type
123//     // It also keeps you from having to use zero and zero_copy
124//     let mut acc_info = ctx.accounts.task.to_account_info();
125//     acc_info.serialize_data(&[
126//         &mut discriminator[..],
127//         &mut task.try_to_vec().unwrap()[..],
128//     ]);
129
130//     msg!("Account initialized");
131
132//     Ok(())
133// }