yellowstone_shield_parser/
accounts.rs

1use solana_program::pubkey::Pubkey;
2use yellowstone_shield_client::{PolicyTrait, accounts};
3pub use yellowstone_shield_client::{types::PermissionStrategy, ID};
4
5#[derive(Debug, Clone)]
6pub struct Policy {
7    pub strategy: PermissionStrategy,
8    pub identities: Vec<Pubkey>,
9}
10
11impl Policy {
12    pub fn new(strategy: PermissionStrategy, identities: Vec<Pubkey>) -> Self {
13        Self {
14            strategy,
15            identities,
16        }
17    }
18}
19
20/// Shield Program State
21#[allow(clippy::large_enum_variant, dead_code)]
22#[derive(Debug, Clone)]
23pub enum ShieldProgramState {
24    Policy(u64, Pubkey, Policy),
25}
26
27impl ShieldProgramState {
28    pub fn try_parse_account_data(
29        slot: u64,
30        pubkey: Pubkey,
31        owner: &Pubkey,
32        data: &[u8],
33        expected_program_id: Option<&Pubkey>,
34    ) -> Result<Self, String> {
35
36        let expected_id = expected_program_id.unwrap_or(&ID);
37        if owner != expected_id {
38            return Err(format!(
39                "Invalid owner: expected {}, got {}",
40                expected_id, owner
41            ));
42        }
43
44        if data.is_empty() {
45            return Err("Data is empty".to_owned());
46        }
47
48        let (strategy, identities) = match data[0] {
49            0 => {
50                let policy = accounts::Policy::from_bytes(data).map_err(|e| e.to_string())?;
51                let strategy = policy.try_strategy().map_err(|e| e.to_string())?;
52                let identities =
53                    accounts::Policy::try_deserialize_identities(data).map_err(|e| e.to_string())?;
54                (strategy, identities)
55            }
56            1 => {
57                let policy = accounts::PolicyV2::from_bytes(data).map_err(|e| e.to_string())?;
58                let strategy = policy.try_strategy().map_err(|e| e.to_string())?;
59                let identities = accounts::PolicyV2::try_deserialize_identities(data)
60                    .map_err(|e| e.to_string())?;
61                (strategy, identities)
62            }
63            _ => return Err("Unsupported data type".to_owned()),
64        };
65
66        let policy = Policy::new(strategy, identities);
67        Ok(ShieldProgramState::Policy(slot, pubkey, policy))
68    }
69}
70
71pub fn parse_account(
72    slot: u64,
73    pubkey: Pubkey,
74    owner: &Pubkey,
75    data: &[u8],
76    expected_program_id: Option<&Pubkey>,
77) -> Result<ShieldProgramState, String> {
78    ShieldProgramState::try_parse_account_data(slot, pubkey, owner, data, expected_program_id)
79}