yellowstone_shield_parser/
instructions.rs1use borsh::BorshDeserialize;
2use solana_program::pubkey::Pubkey;
3use yellowstone_shield_client::instructions::{
4 AddIdentity as AddIdentityIxAccounts, AddIdentityInstructionArgs as AddIdentityIxData,
5 CreatePolicy as CreatePolicyIxAccounts, CreatePolicyInstructionArgs as CreatePolicyIxData,
6 RemoveIdentity as RemoveIdentityIxAccounts,
7 RemoveIdentityInstructionArgs as RemoveIdentityIxData,
8};
9
10use yellowstone_shield_client::ID;
11
12#[derive(Debug)]
14#[allow(dead_code)]
15pub enum ShieldProgramIx {
16 CreatePolicy(CreatePolicyIxAccounts, CreatePolicyIxData),
17 AddIdentity(AddIdentityIxAccounts, AddIdentityIxData),
18 RemoveIdentity(RemoveIdentityIxAccounts, RemoveIdentityIxData),
19}
20
21pub fn parse_instruction(
22 program_id: &Pubkey,
23 accounts: &[Pubkey],
24 data: &[u8],
25) -> Result<ShieldProgramIx, String> {
26 if program_id != &ID {
27 return Err(format!(
28 "Invalid program ID: expected {}, got {}",
29 ID, program_id
30 ));
31 }
32
33 if data.is_empty() {
34 return Err("Instruction data is empty".to_owned());
35 }
36
37 let accounts_len = accounts.len();
38 let ix_discriminator = data[0];
39 let mut ix_data = &data[1..];
40
41 match ix_discriminator {
42 0 => {
43 check_min_accounts_req(accounts_len, 6)?;
44 let ix_accounts = CreatePolicyIxAccounts {
45 mint: accounts[0],
46 token_account: accounts[1],
47 policy: accounts[2],
48 payer: accounts[3],
49 owner: accounts[4],
50 system_program: accounts[5],
51 };
52 let de_ix_data: CreatePolicyIxData =
53 BorshDeserialize::deserialize(&mut ix_data).map_err(|e| e.to_string())?;
54 Ok(ShieldProgramIx::CreatePolicy(ix_accounts, de_ix_data))
55 }
56 1 => {
57 check_min_accounts_req(accounts_len, 6)?;
58 let ix_accounts = AddIdentityIxAccounts {
59 mint: accounts[0],
60 token_account: accounts[1],
61 policy: accounts[2],
62 payer: accounts[3],
63 owner: accounts[4],
64 system_program: accounts[5],
65 };
66 let de_ix_data: AddIdentityIxData =
67 BorshDeserialize::deserialize(&mut ix_data).map_err(|e| e.to_string())?;
68 Ok(ShieldProgramIx::AddIdentity(ix_accounts, de_ix_data))
69 }
70 2 => {
71 check_min_accounts_req(accounts_len, 4)?;
72 let ix_accounts = RemoveIdentityIxAccounts {
73 mint: accounts[0],
74 token_account: accounts[1],
75 policy: accounts[2],
76 owner: accounts[3],
77 };
78 let de_ix_data: RemoveIdentityIxData =
79 BorshDeserialize::deserialize(&mut ix_data).map_err(|e| e.to_string())?;
80 Ok(ShieldProgramIx::RemoveIdentity(ix_accounts, de_ix_data))
81 }
82 _ => Err("Invalid Instruction discriminator".to_owned()),
83 }
84}
85
86fn check_min_accounts_req(actual: usize, expected: usize) -> Result<(), String> {
87 if actual < expected {
88 Err(format!(
89 "Too few accounts provided: expected {expected}, got {actual}"
90 ))
91 } else {
92 Ok(())
93 }
94}