1use {
4 crate::{error::SinglePoolError, find_pool_address},
5 borsh::{BorshDeserialize, BorshSchema, BorshSerialize},
6 solana_account_info::AccountInfo,
7 solana_borsh::v1::try_from_slice_unchecked,
8 solana_program_error::ProgramError,
9 solana_pubkey::Pubkey,
10};
11
12#[derive(Clone, Debug, Default, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
14pub enum SinglePoolAccountType {
15 #[default]
17 Uninitialized,
18 Pool,
20}
21
22#[derive(Clone, Debug, Default, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
24pub struct SinglePool {
25 pub account_type: SinglePoolAccountType,
27 pub vote_account_address: Pubkey,
29}
30impl SinglePool {
31 pub const fn size_of() -> usize {
33 33
34 }
35
36 pub fn from_account_info(
38 account_info: &AccountInfo,
39 program_id: &Pubkey,
40 ) -> Result<Self, ProgramError> {
41 if account_info.data_len() == 0 || account_info.owner != program_id {
43 return Err(SinglePoolError::InvalidPoolAccount.into());
44 }
45
46 let pool = try_from_slice_unchecked::<SinglePool>(&account_info.data.borrow())?;
47
48 if pool.account_type != SinglePoolAccountType::Pool {
50 return Err(SinglePoolError::InvalidPoolAccount.into());
51 }
52
53 if *account_info.key != find_pool_address(program_id, &pool.vote_account_address) {
57 return Err(SinglePoolError::InvalidPoolAccount.into());
58 }
59
60 Ok(pool)
61 }
62}
63
64#[cfg(test)]
65mod tests {
66 use {super::*, solana_borsh::v1::get_packed_len};
67
68 #[test]
69 fn single_pool_size_of() {
70 assert_eq!(SinglePool::size_of(), get_packed_len::<SinglePool>());
71 }
72}