phoenix/program/validation/checkers/
mod.rs

1use crate::program::error::assert_with_msg;
2use solana_program::{
3    account_info::AccountInfo, program_error::ProgramError, pubkey::Pubkey, system_program,
4};
5use std::ops::Deref;
6
7pub mod phoenix_checkers;
8pub mod token_checkers;
9
10pub use token_checkers::*;
11
12#[derive(Clone)]
13pub struct PDA<'a, 'info> {
14    info: &'a AccountInfo<'info>,
15}
16
17impl<'a, 'info> PDA<'a, 'info> {
18    pub fn new(
19        info: &'a AccountInfo<'info>,
20        known_address: &Pubkey,
21    ) -> Result<PDA<'a, 'info>, ProgramError> {
22        assert_with_msg(
23            info.key == known_address,
24            ProgramError::InvalidInstructionData,
25            "Incorrect account key",
26        )?;
27        Ok(Self { info })
28    }
29}
30
31impl<'a, 'info> AsRef<AccountInfo<'info>> for PDA<'a, 'info> {
32    fn as_ref(&self) -> &AccountInfo<'info> {
33        self.info
34    }
35}
36
37impl<'a, 'info> Deref for PDA<'a, 'info> {
38    type Target = AccountInfo<'info>;
39
40    fn deref(&self) -> &Self::Target {
41        self.info
42    }
43}
44
45#[derive(Clone)]
46pub struct Program<'a, 'info> {
47    info: &'a AccountInfo<'info>,
48}
49
50impl<'a, 'info> Program<'a, 'info> {
51    pub fn new(
52        info: &'a AccountInfo<'info>,
53        expected_program_id: &Pubkey,
54    ) -> Result<Program<'a, 'info>, ProgramError> {
55        assert_with_msg(
56            info.key == expected_program_id,
57            ProgramError::IncorrectProgramId,
58            "Incorrect program id",
59        )?;
60        Ok(Self { info })
61    }
62}
63
64impl<'a, 'info> AsRef<AccountInfo<'info>> for Program<'a, 'info> {
65    fn as_ref(&self) -> &AccountInfo<'info> {
66        self.info
67    }
68}
69
70impl<'a, 'info> Deref for Program<'a, 'info> {
71    type Target = AccountInfo<'info>;
72
73    fn deref(&self) -> &Self::Target {
74        self.info
75    }
76}
77
78#[derive(Clone)]
79pub struct Signer<'a, 'info> {
80    info: &'a AccountInfo<'info>,
81}
82
83impl<'a, 'info> Signer<'a, 'info> {
84    pub fn new(info: &'a AccountInfo<'info>) -> Result<Signer<'a, 'info>, ProgramError> {
85        assert_with_msg(
86            info.is_signer,
87            ProgramError::MissingRequiredSignature,
88            "Missing required signature",
89        )?;
90        Ok(Self { info })
91    }
92
93    pub fn new_with_key(
94        info: &'a AccountInfo<'info>,
95        key: &Pubkey,
96    ) -> Result<Signer<'a, 'info>, ProgramError> {
97        let signer = Self::new(info)?;
98        assert_with_msg(
99            signer.key == key,
100            ProgramError::MissingRequiredSignature,
101            "Incorrect key for signer",
102        )?;
103        Ok(signer)
104    }
105
106    pub fn new_payer(info: &'a AccountInfo<'info>) -> Result<Signer<'a, 'info>, ProgramError> {
107        assert_with_msg(
108            info.is_writable,
109            ProgramError::InvalidInstructionData,
110            "Payer is not writable",
111        )?;
112        assert_with_msg(
113            info.is_signer,
114            ProgramError::MissingRequiredSignature,
115            "Missing required signature for payer",
116        )?;
117        Ok(Self { info })
118    }
119}
120
121impl<'a, 'info> AsRef<AccountInfo<'info>> for Signer<'a, 'info> {
122    fn as_ref(&self) -> &AccountInfo<'info> {
123        self.info
124    }
125}
126
127impl<'a, 'info> Deref for Signer<'a, 'info> {
128    type Target = AccountInfo<'info>;
129
130    fn deref(&self) -> &Self::Target {
131        self.info
132    }
133}
134
135#[derive(Clone)]
136pub struct EmptyAccount<'a, 'info> {
137    info: &'a AccountInfo<'info>,
138}
139
140impl<'a, 'info> EmptyAccount<'a, 'info> {
141    pub fn new(info: &'a AccountInfo<'info>) -> Result<EmptyAccount<'a, 'info>, ProgramError> {
142        assert_with_msg(
143            info.data_is_empty(),
144            ProgramError::InvalidAccountData,
145            "Account must be uninitialized",
146        )?;
147        assert_with_msg(
148            info.owner == &system_program::id(),
149            ProgramError::IllegalOwner,
150            "Empty accounts must be owned by the system program",
151        )?;
152        Ok(Self { info })
153    }
154}
155
156impl<'a, 'info> AsRef<AccountInfo<'info>> for EmptyAccount<'a, 'info> {
157    fn as_ref(&self) -> &AccountInfo<'info> {
158        self.info
159    }
160}
161
162impl<'a, 'info> Deref for EmptyAccount<'a, 'info> {
163    type Target = AccountInfo<'info>;
164
165    fn deref(&self) -> &Self::Target {
166        self.info
167    }
168}