pda_counter/
lib.rs

1use anchor_lang::prelude::*;
2
3//program ID, prewritten with anchor init, but it can also be retrieve from target/deploy/*.json
4declare_id!("3mQdn2TX5x4sX5Niisy6Q5B8yHDqtGxvYUXj58DCcuJ7");
5
6#[program]
7pub mod pda_counter {
8    use super::*;
9
10    //Initializing a new counter PDA, setting the count = 0
11    pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
12        let counter = &mut ctx.accounts.counter; //instance created
13        counter.count = 0; //initialied an account using that instance
14        counter.user = *ctx.accounts.user.key;
15
16        //emit! emits the event (that counter has been inited), written far below this program
17        emit!(CounterInit {
18            user: counter.user,
19            count: counter.count,
20        });
21
22        Ok(())
23    }
24
25    //Increments the counter, after verify if user is the owner.
26    pub fn increment(ctx: Context<Increment>) -> Result<()> {
27        let counter = &mut ctx.accounts.counter;
28
29        //ownership check
30        if counter.user != *ctx.accounts.user.key {
31            return err!(CounterError::InvalidUser);
32        }
33        counter.count += 1;
34
35        //Emits CounterIncrease event
36        emit!(CounterIncrease {
37            user: counter.user,
38            count: counter.count,
39        });
40
41        Ok(())
42    }
43
44    //Reset the counter to 0 and closes the account, returning the SOL.
45    pub fn reset(ctx: Context<Reset>) -> Result<()> {
46        let counter = &mut ctx.accounts.counter;
47
48        //ownership checking
49        if counter.user != *ctx.accounts.user.key {
50            return err!(CounterError::InvalidUser);
51        }
52        counter.count = 0;
53
54        //emit reset event
55        emit!(CounterReset { user: counter.user });
56
57        Ok(())
58    }
59}
60
61// ──・❥ ────・❥ ────・❥ ────・❥ ────Account Contexts────・❥ ────・❥ ────・❥ ────・❥ ────・❥ ──
62
63//Context for initialising the PDA counter
64#[derive(Accounts)]
65pub struct Initialize<'info> {
66    #[account(
67        init,
68        payer = user,
69        space = 8 + 32 + 8,
70        seeds = [b"counte", user.key().as_ref()], bump //the [boxed] item wasn't mandatory, anchor provide bump
71    )]
72    pub counter: Account<'info, Counter>,
73    #[account(mut)]
74    pub user: Signer<'info>,
75    pub system_program: Program<'info, System>,
76}
77
78//Context for incrementing the counter
79#[derive(Accounts)]
80pub struct Increment<'info> {
81    #[account(
82        mut,
83        seeds = [b"counte", user.key().as_ref()], bump
84    )]
85    pub counter: Account<'info, Counter>,
86    pub user: Signer<'info>,
87}
88
89//Context for reset and close the account
90#[derive(Accounts)]
91pub struct Reset<'info> {
92    #[account(mut,
93        seeds = [b"counte", user.key().as_ref()], bump,
94        close = user,
95    )]
96    pub counter: Account<'info, Counter>,
97    pub user: Signer<'info>,
98}
99
100// ──・❥ ────・❥ ────・❥ ────・❥ ────Account Data────・❥ ────・❥ ────・❥ ────・❥ ────・❥ ──
101
102//the final data structure stored in the PDA
103#[account]
104pub struct Counter {
105    pub user: Pubkey,
106    pub count: u64,
107}
108
109// ──・❥ ────・❥ ────・❥ ────・❥ ────Events────・❥ ────・❥ ────・❥ ────・❥ ────・❥ ──
110
111//Init event
112#[event]
113pub struct CounterInit {
114    pub user: Pubkey,
115    pub count: u64,
116}
117
118//Increment event
119#[event]
120pub struct CounterIncrease {
121    pub user: Pubkey,
122    pub count: u64,
123}
124
125//Reset event
126#[event]
127pub struct CounterReset {
128    pub user: Pubkey,
129}
130
131// ──・❥ ────・❥ ────・❥ ────・❥ ────Custom Errors────・❥ ────・❥ ────・❥ ────・❥ ────・❥ ──
132
133//If user is not the owner, this error will be used.
134#[error_code]
135pub enum CounterError {
136    #[msg("Unauthorised User")]
137    InvalidUser,
138}