gmsol_callback/instructions/
action_callback.rs

1use anchor_lang::prelude::*;
2
3use crate::{
4    states::{ActionStats, Config, ACTION_STATS_SEED, CALLER_PROGRAM_ID},
5    CALLBACK_AUTHORITY_SEED,
6};
7
8/// Callback accounts.
9#[derive(Accounts)]
10#[instruction(authority_bump: u8, action_kind: u8)]
11pub struct OnCallback<'info> {
12    /// The callback authority.
13    #[account(
14        seeds = [CALLBACK_AUTHORITY_SEED],
15        bump = authority_bump,
16        seeds::program = CALLER_PROGRAM_ID,
17    )]
18    pub authority: Signer<'info>,
19    /// The account used for storing shared data.
20    #[account(mut)]
21    pub shared_data: Account<'info, Config>,
22    /// The account used for storing partitioned data.
23    #[account(
24        mut,
25        seeds = [
26            ACTION_STATS_SEED,
27            owner.key.as_ref(),
28            &[action_kind],
29        ],
30        bump = partitioned_data.bump,
31        constraint = partitioned_data.initialized,
32        constraint = partitioned_data.action_kind == action_kind,
33        has_one = owner,
34    )]
35    pub partitioned_data: Account<'info, ActionStats>,
36    /// The owner of the action account.
37    /// CHECK: This account is unchecked because only its address is used.
38    pub owner: UncheckedAccount<'info>,
39    /// The action account.
40    /// CHECK: This account is unchecked because only its address is used.
41    pub action: UncheckedAccount<'info>,
42}
43
44impl OnCallback<'_> {
45    pub(crate) fn invoke(
46        trigger: On,
47        ctx: Context<Self>,
48        _authority_bump: u8,
49        _action_kind: u8,
50        _callback_version: u8,
51        success: bool,
52        extra_account_count: u8,
53    ) -> Result<()> {
54        debug_assert!(ctx.remaining_accounts.len() >= usize::from(extra_account_count));
55        ctx.accounts.shared_data.calls += 1;
56        match trigger {
57            On::Created => ctx.accounts.handle_created(success),
58            On::Updated => ctx.accounts.handle_updated(success),
59            On::Executed => ctx.accounts.handle_executed(success),
60            On::Closed => ctx.accounts.handle_closed(success),
61        }
62    }
63
64    fn handle_created(&mut self, success: bool) -> Result<()> {
65        self.partitioned_data.total_created += 1;
66        self.partitioned_data.last_created_at = Clock::get()?.unix_timestamp;
67
68        msg!(
69            "{}: on_created, success={} calls={}",
70            self.shared_data.prefix,
71            success,
72            self.shared_data.calls
73        );
74        Ok(())
75    }
76
77    fn handle_updated(&mut self, success: bool) -> Result<()> {
78        self.partitioned_data.update_count += 1;
79        self.partitioned_data.last_updated_at = Clock::get()?.unix_timestamp;
80
81        msg!(
82            "{}: on_updated, success={} calls={}",
83            self.shared_data.prefix,
84            success,
85            self.shared_data.calls
86        );
87        Ok(())
88    }
89
90    fn handle_executed(&mut self, success: bool) -> Result<()> {
91        self.partitioned_data.total_executed += 1;
92        self.partitioned_data.last_executed_at = Clock::get()?.unix_timestamp;
93
94        msg!(
95            "{}: on_executed, success={} calls={}",
96            self.shared_data.prefix,
97            success,
98            self.shared_data.calls
99        );
100        Ok(())
101    }
102
103    fn handle_closed(&mut self, success: bool) -> Result<()> {
104        self.partitioned_data.total_closed += 1;
105        self.partitioned_data.last_closed_at = Clock::get()?.unix_timestamp;
106
107        msg!(
108            "{}: on_closed, success={} calls={}",
109            self.shared_data.prefix,
110            success,
111            self.shared_data.calls
112        );
113        Ok(())
114    }
115}
116
117/// Callback trigger.
118pub(crate) enum On {
119    /// On created.
120    Created,
121    /// On updated.
122    Updated,
123    /// On executed.
124    Executed,
125    /// On closed.
126    Closed,
127}