cow_settlement_interface/
token_program.rs1use crate::Pubkey;
4use solana_program_error::ProgramError;
5pub use solana_sdk_ids::sysvar::instructions::ID as INSTRUCTIONS_SYSVAR_ID;
6
7#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
9pub enum TokenProgram {
10 SplToken,
12 Token2022,
14}
15
16impl TokenProgram {
17 pub const ALL: [Self; 2] = [Self::SplToken, Self::Token2022];
19
20 pub const fn address(self) -> Pubkey {
22 match self {
23 Self::SplToken => spl_token_2022_interface::inline_spl_token::ID,
24 Self::Token2022 => spl_token_2022_interface::ID,
25 }
26 }
27}
28
29impl TryFrom<&Pubkey> for TokenProgram {
30 type Error = ProgramError;
31
32 fn try_from(address: &Pubkey) -> Result<Self, Self::Error> {
35 Self::ALL
36 .into_iter()
37 .find(|program| program.address() == *address)
38 .ok_or(ProgramError::IncorrectProgramId)
39 }
40}
41
42#[cfg(test)]
43mod tests {
44 use super::*;
45 use crate::fixtures::pubkey_from_seed;
46
47 const _: () = match TokenProgram::SplToken {
50 TokenProgram::SplToken | TokenProgram::Token2022 => (),
51 };
52
53 #[test]
54 fn every_program_resolves_from_its_own_address() {
55 for program in TokenProgram::ALL {
56 let address = program.address();
57 assert_eq!(
58 TokenProgram::try_from(&address),
59 Ok(program),
60 "{program:?} should resolve from {address}",
61 );
62 }
63 }
64
65 #[test]
66 fn unrelated_program_cannot_be_resolved_as_token_program() {
67 assert_eq!(
68 TokenProgram::try_from(&pubkey_from_seed("not a token program")),
69 Err(ProgramError::IncorrectProgramId),
70 );
71 }
72}