//! This code was AUTOGENERATED using the codama library.
//! Please DO NOT EDIT THIS FILE, instead use visitors
//! to add features, then rerun codama to update it.
//!
//! <https://github.com/codama-idl/codama>
//!

use crate::instructions::{
    AdminCancelOrders as AdminCancelOrdersIxAccounts,
    AdminCancelOrdersInstructionArgs as AdminCancelOrdersIxData,
    CreateConfigAccount as CreateConfigAccountIxAccounts, Deposit as DepositIxAccounts,
    DepositInstructionArgs as DepositIxData, Initialize as InitializeIxAccounts,
    Initialize2 as Initialize2IxAccounts, Initialize2InstructionArgs as Initialize2IxData,
    InitializeInstructionArgs as InitializeIxData,
    MigrateToOpenBook as MigrateToOpenBookIxAccounts, MonitorStep as MonitorStepIxAccounts,
    MonitorStepInstructionArgs as MonitorStepIxData, PreInitialize as PreInitializeIxAccounts,
    PreInitializeInstructionArgs as PreInitializeIxData, SetParams as SetParamsIxAccounts,
    SetParamsInstructionArgs as SetParamsIxData, SimulateInfo as SimulateInfoIxAccounts,
    SimulateInfoInstructionArgs as SimulateInfoIxData, SwapBaseIn as SwapBaseInIxAccounts,
    SwapBaseInInstructionArgs as SwapBaseInIxData, SwapBaseOut as SwapBaseOutIxAccounts,
    SwapBaseOutInstructionArgs as SwapBaseOutIxData,
    UpdateConfigAccount as UpdateConfigAccountIxAccounts,
    UpdateConfigAccountInstructionArgs as UpdateConfigAccountIxData,
    Withdraw as WithdrawIxAccounts, WithdrawInstructionArgs as WithdrawIxData,
    WithdrawPnl as WithdrawPnlIxAccounts, WithdrawSrm as WithdrawSrmIxAccounts,
    WithdrawSrmInstructionArgs as WithdrawSrmIxData,
};
use crate::ID;
use borsh::BorshDeserialize;

/// RaydiumAmm Instructions
#[derive(Debug)]
#[cfg_attr(feature = "tracing", derive(strum_macros::Display))]
pub enum RaydiumAmmProgramIx {
    Initialize(InitializeIxAccounts, InitializeIxData),
    Initialize2(Initialize2IxAccounts, Initialize2IxData),
    MonitorStep(MonitorStepIxAccounts, MonitorStepIxData),
    Deposit(DepositIxAccounts, DepositIxData),
    Withdraw(WithdrawIxAccounts, WithdrawIxData),
    MigrateToOpenBook(MigrateToOpenBookIxAccounts),
    SetParams(SetParamsIxAccounts, SetParamsIxData),
    WithdrawPnl(WithdrawPnlIxAccounts),
    WithdrawSrm(WithdrawSrmIxAccounts, WithdrawSrmIxData),
    SwapBaseIn(SwapBaseInIxAccounts, SwapBaseInIxData),
    PreInitialize(PreInitializeIxAccounts, PreInitializeIxData),
    SwapBaseOut(SwapBaseOutIxAccounts, SwapBaseOutIxData),
    SimulateInfo(SimulateInfoIxAccounts, SimulateInfoIxData),
    AdminCancelOrders(AdminCancelOrdersIxAccounts, AdminCancelOrdersIxData),
    CreateConfigAccount(CreateConfigAccountIxAccounts),
    UpdateConfigAccount(UpdateConfigAccountIxAccounts, UpdateConfigAccountIxData),
}

#[derive(Debug, Copy, Clone)]
pub struct InstructionParser;

impl yellowstone_vixen_core::Parser for InstructionParser {
    type Input = yellowstone_vixen_core::instruction::InstructionUpdate;
    type Output = RaydiumAmmProgramIx;

    fn id(&self) -> std::borrow::Cow<str> {
        "RaydiumAmm::InstructionParser".into()
    }

    fn prefilter(&self) -> yellowstone_vixen_core::Prefilter {
        yellowstone_vixen_core::Prefilter::builder()
            .transaction_accounts([ID])
            .build()
            .unwrap()
    }

    async fn parse(
        &self,
        ix_update: &yellowstone_vixen_core::instruction::InstructionUpdate,
    ) -> yellowstone_vixen_core::ParseResult<Self::Output> {
        if ix_update.program.equals_ref(ID) {
            InstructionParser::parse_impl(ix_update)
        } else {
            Err(yellowstone_vixen_core::ParseError::Filtered)
        }
    }
}

impl yellowstone_vixen_core::ProgramParser for InstructionParser {
    #[inline]
    fn program_id(&self) -> yellowstone_vixen_core::Pubkey {
        ID.to_bytes().into()
    }
}

impl InstructionParser {
    pub(crate) fn parse_impl(
        ix: &yellowstone_vixen_core::instruction::InstructionUpdate,
    ) -> yellowstone_vixen_core::ParseResult<RaydiumAmmProgramIx> {
        let accounts_len = ix.accounts.len();

        let ix_discriminator: [u8; 1] = ix.data[0..1].try_into()?;
        let mut ix_data = &ix.data[1..];
        let ix = match ix_discriminator {
            [0] => {
                check_min_accounts_req(accounts_len, 18)?;
                let ix_accounts = InitializeIxAccounts {
                    token_program: ix.accounts[0].0.into(),
                    system_program: ix.accounts[1].0.into(),
                    rent: ix.accounts[2].0.into(),
                    amm: ix.accounts[3].0.into(),
                    amm_authority: ix.accounts[4].0.into(),
                    amm_open_orders: ix.accounts[5].0.into(),
                    lp_mint_address: ix.accounts[6].0.into(),
                    coin_mint_address: ix.accounts[7].0.into(),
                    pc_mint_address: ix.accounts[8].0.into(),
                    pool_coin_token_account: ix.accounts[9].0.into(),
                    pool_pc_token_account: ix.accounts[10].0.into(),
                    pool_withdraw_queue: ix.accounts[11].0.into(),
                    pool_target_orders_account: ix.accounts[12].0.into(),
                    user_lp_token_account: ix.accounts[13].0.into(),
                    pool_temp_lp_token_account: ix.accounts[14].0.into(),
                    serum_program: ix.accounts[15].0.into(),
                    serum_market: ix.accounts[16].0.into(),
                    user_wallet: ix.accounts[17].0.into(),
                };
                let de_ix_data: InitializeIxData = BorshDeserialize::deserialize(&mut ix_data)?;
                Ok(RaydiumAmmProgramIx::Initialize(ix_accounts, de_ix_data))
            }
            [1] => {
                check_min_accounts_req(accounts_len, 21)?;
                let ix_accounts = Initialize2IxAccounts {
                    token_program: ix.accounts[0].0.into(),
                    spl_associated_token_account: ix.accounts[1].0.into(),
                    system_program: ix.accounts[2].0.into(),
                    rent: ix.accounts[3].0.into(),
                    amm: ix.accounts[4].0.into(),
                    amm_authority: ix.accounts[5].0.into(),
                    amm_open_orders: ix.accounts[6].0.into(),
                    lp_mint: ix.accounts[7].0.into(),
                    coin_mint: ix.accounts[8].0.into(),
                    pc_mint: ix.accounts[9].0.into(),
                    pool_coin_token_account: ix.accounts[10].0.into(),
                    pool_pc_token_account: ix.accounts[11].0.into(),
                    pool_withdraw_queue: ix.accounts[12].0.into(),
                    amm_target_orders: ix.accounts[13].0.into(),
                    pool_temp_lp: ix.accounts[14].0.into(),
                    serum_program: ix.accounts[15].0.into(),
                    serum_market: ix.accounts[16].0.into(),
                    user_wallet: ix.accounts[17].0.into(),
                    user_token_coin: ix.accounts[18].0.into(),
                    user_token_pc: ix.accounts[19].0.into(),
                    user_lp_token_account: ix.accounts[20].0.into(),
                };
                let de_ix_data: Initialize2IxData = BorshDeserialize::deserialize(&mut ix_data)?;
                Ok(RaydiumAmmProgramIx::Initialize2(ix_accounts, de_ix_data))
            }
            [2] => {
                check_min_accounts_req(accounts_len, 19)?;
                let ix_accounts = MonitorStepIxAccounts {
                    token_program: ix.accounts[0].0.into(),
                    rent: ix.accounts[1].0.into(),
                    clock: ix.accounts[2].0.into(),
                    amm: ix.accounts[3].0.into(),
                    amm_authority: ix.accounts[4].0.into(),
                    amm_open_orders: ix.accounts[5].0.into(),
                    amm_target_orders: ix.accounts[6].0.into(),
                    pool_coin_token_account: ix.accounts[7].0.into(),
                    pool_pc_token_account: ix.accounts[8].0.into(),
                    pool_withdraw_queue: ix.accounts[9].0.into(),
                    serum_program: ix.accounts[10].0.into(),
                    serum_market: ix.accounts[11].0.into(),
                    serum_coin_vault_account: ix.accounts[12].0.into(),
                    serum_pc_vault_account: ix.accounts[13].0.into(),
                    serum_vault_signer: ix.accounts[14].0.into(),
                    serum_req_q: ix.accounts[15].0.into(),
                    serum_event_q: ix.accounts[16].0.into(),
                    serum_bids: ix.accounts[17].0.into(),
                    serum_asks: ix.accounts[18].0.into(),
                };
                let de_ix_data: MonitorStepIxData = BorshDeserialize::deserialize(&mut ix_data)?;
                Ok(RaydiumAmmProgramIx::MonitorStep(ix_accounts, de_ix_data))
            }
            [3] => {
                check_min_accounts_req(accounts_len, 14)?;
                let ix_accounts = DepositIxAccounts {
                    token_program: ix.accounts[0].0.into(),
                    amm: ix.accounts[1].0.into(),
                    amm_authority: ix.accounts[2].0.into(),
                    amm_open_orders: ix.accounts[3].0.into(),
                    amm_target_orders: ix.accounts[4].0.into(),
                    lp_mint_address: ix.accounts[5].0.into(),
                    pool_coin_token_account: ix.accounts[6].0.into(),
                    pool_pc_token_account: ix.accounts[7].0.into(),
                    serum_market: ix.accounts[8].0.into(),
                    user_coin_token_account: ix.accounts[9].0.into(),
                    user_pc_token_account: ix.accounts[10].0.into(),
                    user_lp_token_account: ix.accounts[11].0.into(),
                    user_owner: ix.accounts[12].0.into(),
                    serum_event_queue: ix.accounts[13].0.into(),
                };
                let de_ix_data: DepositIxData = BorshDeserialize::deserialize(&mut ix_data)?;
                Ok(RaydiumAmmProgramIx::Deposit(ix_accounts, de_ix_data))
            }
            [4] => {
                check_min_accounts_req(accounts_len, 22)?;
                let ix_accounts = WithdrawIxAccounts {
                    token_program: ix.accounts[0].0.into(),
                    amm: ix.accounts[1].0.into(),
                    amm_authority: ix.accounts[2].0.into(),
                    amm_open_orders: ix.accounts[3].0.into(),
                    amm_target_orders: ix.accounts[4].0.into(),
                    lp_mint_address: ix.accounts[5].0.into(),
                    pool_coin_token_account: ix.accounts[6].0.into(),
                    pool_pc_token_account: ix.accounts[7].0.into(),
                    pool_withdraw_queue: ix.accounts[8].0.into(),
                    pool_temp_lp_token_account: ix.accounts[9].0.into(),
                    serum_program: ix.accounts[10].0.into(),
                    serum_market: ix.accounts[11].0.into(),
                    serum_coin_vault_account: ix.accounts[12].0.into(),
                    serum_pc_vault_account: ix.accounts[13].0.into(),
                    serum_vault_signer: ix.accounts[14].0.into(),
                    user_lp_token_account: ix.accounts[15].0.into(),
                    uer_coin_token_account: ix.accounts[16].0.into(),
                    uer_pc_token_account: ix.accounts[17].0.into(),
                    user_owner: ix.accounts[18].0.into(),
                    serum_event_q: ix.accounts[19].0.into(),
                    serum_bids: ix.accounts[20].0.into(),
                    serum_asks: ix.accounts[21].0.into(),
                };
                let de_ix_data: WithdrawIxData = BorshDeserialize::deserialize(&mut ix_data)?;
                Ok(RaydiumAmmProgramIx::Withdraw(ix_accounts, de_ix_data))
            }
            [5] => {
                check_min_accounts_req(accounts_len, 21)?;
                let ix_accounts = MigrateToOpenBookIxAccounts {
                    token_program: ix.accounts[0].0.into(),
                    system_program: ix.accounts[1].0.into(),
                    rent: ix.accounts[2].0.into(),
                    amm: ix.accounts[3].0.into(),
                    amm_authority: ix.accounts[4].0.into(),
                    amm_open_orders: ix.accounts[5].0.into(),
                    amm_token_coin: ix.accounts[6].0.into(),
                    amm_token_pc: ix.accounts[7].0.into(),
                    amm_target_orders: ix.accounts[8].0.into(),
                    serum_program: ix.accounts[9].0.into(),
                    serum_market: ix.accounts[10].0.into(),
                    serum_bids: ix.accounts[11].0.into(),
                    serum_asks: ix.accounts[12].0.into(),
                    serum_event_queue: ix.accounts[13].0.into(),
                    serum_coin_vault: ix.accounts[14].0.into(),
                    serum_pc_vault: ix.accounts[15].0.into(),
                    serum_vault_signer: ix.accounts[16].0.into(),
                    new_amm_open_orders: ix.accounts[17].0.into(),
                    new_serum_program: ix.accounts[18].0.into(),
                    new_serum_market: ix.accounts[19].0.into(),
                    admin: ix.accounts[20].0.into(),
                };
                Ok(RaydiumAmmProgramIx::MigrateToOpenBook(ix_accounts))
            }
            [6] => {
                check_min_accounts_req(accounts_len, 16)?;
                let ix_accounts = SetParamsIxAccounts {
                    token_program: ix.accounts[0].0.into(),
                    amm: ix.accounts[1].0.into(),
                    amm_authority: ix.accounts[2].0.into(),
                    amm_open_orders: ix.accounts[3].0.into(),
                    amm_target_orders: ix.accounts[4].0.into(),
                    amm_coin_vault: ix.accounts[5].0.into(),
                    amm_pc_vault: ix.accounts[6].0.into(),
                    serum_program: ix.accounts[7].0.into(),
                    serum_market: ix.accounts[8].0.into(),
                    serum_coin_vault: ix.accounts[9].0.into(),
                    serum_pc_vault: ix.accounts[10].0.into(),
                    serum_vault_signer: ix.accounts[11].0.into(),
                    serum_event_queue: ix.accounts[12].0.into(),
                    serum_bids: ix.accounts[13].0.into(),
                    serum_asks: ix.accounts[14].0.into(),
                    amm_admin_account: ix.accounts[15].0.into(),
                };
                let de_ix_data: SetParamsIxData = BorshDeserialize::deserialize(&mut ix_data)?;
                Ok(RaydiumAmmProgramIx::SetParams(ix_accounts, de_ix_data))
            }
            [7] => {
                check_min_accounts_req(accounts_len, 17)?;
                let ix_accounts = WithdrawPnlIxAccounts {
                    token_program: ix.accounts[0].0.into(),
                    amm: ix.accounts[1].0.into(),
                    amm_config: ix.accounts[2].0.into(),
                    amm_authority: ix.accounts[3].0.into(),
                    amm_open_orders: ix.accounts[4].0.into(),
                    pool_coin_token_account: ix.accounts[5].0.into(),
                    pool_pc_token_account: ix.accounts[6].0.into(),
                    coin_pnl_token_account: ix.accounts[7].0.into(),
                    pc_pnl_token_account: ix.accounts[8].0.into(),
                    pnl_owner_account: ix.accounts[9].0.into(),
                    amm_target_orders: ix.accounts[10].0.into(),
                    serum_program: ix.accounts[11].0.into(),
                    serum_market: ix.accounts[12].0.into(),
                    serum_event_queue: ix.accounts[13].0.into(),
                    serum_coin_vault_account: ix.accounts[14].0.into(),
                    serum_pc_vault_account: ix.accounts[15].0.into(),
                    serum_vault_signer: ix.accounts[16].0.into(),
                };
                Ok(RaydiumAmmProgramIx::WithdrawPnl(ix_accounts))
            }
            [8] => {
                check_min_accounts_req(accounts_len, 6)?;
                let ix_accounts = WithdrawSrmIxAccounts {
                    token_program: ix.accounts[0].0.into(),
                    amm: ix.accounts[1].0.into(),
                    amm_owner_account: ix.accounts[2].0.into(),
                    amm_authority: ix.accounts[3].0.into(),
                    srm_token: ix.accounts[4].0.into(),
                    dest_srm_token: ix.accounts[5].0.into(),
                };
                let de_ix_data: WithdrawSrmIxData = BorshDeserialize::deserialize(&mut ix_data)?;
                Ok(RaydiumAmmProgramIx::WithdrawSrm(ix_accounts, de_ix_data))
            }
            [9] => {
                check_min_accounts_req(accounts_len, 18)?;
                let ix_accounts = SwapBaseInIxAccounts {
                    token_program: ix.accounts[0].0.into(),
                    amm: ix.accounts[1].0.into(),
                    amm_authority: ix.accounts[2].0.into(),
                    amm_open_orders: ix.accounts[3].0.into(),
                    amm_target_orders: ix.accounts[4].0.into(),
                    pool_coin_token_account: ix.accounts[5].0.into(),
                    pool_pc_token_account: ix.accounts[6].0.into(),
                    serum_program: ix.accounts[7].0.into(),
                    serum_market: ix.accounts[8].0.into(),
                    serum_bids: ix.accounts[9].0.into(),
                    serum_asks: ix.accounts[10].0.into(),
                    serum_event_queue: ix.accounts[11].0.into(),
                    serum_coin_vault_account: ix.accounts[12].0.into(),
                    serum_pc_vault_account: ix.accounts[13].0.into(),
                    serum_vault_signer: ix.accounts[14].0.into(),
                    uer_source_token_account: ix.accounts[15].0.into(),
                    uer_destination_token_account: ix.accounts[16].0.into(),
                    user_source_owner: ix.accounts[17].0.into(),
                };
                let de_ix_data: SwapBaseInIxData = BorshDeserialize::deserialize(&mut ix_data)?;
                Ok(RaydiumAmmProgramIx::SwapBaseIn(ix_accounts, de_ix_data))
            }
            [10] => {
                check_min_accounts_req(accounts_len, 14)?;
                let ix_accounts = PreInitializeIxAccounts {
                    token_program: ix.accounts[0].0.into(),
                    system_program: ix.accounts[1].0.into(),
                    rent: ix.accounts[2].0.into(),
                    amm_target_orders: ix.accounts[3].0.into(),
                    pool_withdraw_queue: ix.accounts[4].0.into(),
                    amm_authority: ix.accounts[5].0.into(),
                    lp_mint_address: ix.accounts[6].0.into(),
                    coin_mint_address: ix.accounts[7].0.into(),
                    pc_mint_address: ix.accounts[8].0.into(),
                    pool_coin_token_account: ix.accounts[9].0.into(),
                    pool_pc_token_account: ix.accounts[10].0.into(),
                    pool_temp_lp_token_account: ix.accounts[11].0.into(),
                    serum_market: ix.accounts[12].0.into(),
                    user_wallet: ix.accounts[13].0.into(),
                };
                let de_ix_data: PreInitializeIxData = BorshDeserialize::deserialize(&mut ix_data)?;
                Ok(RaydiumAmmProgramIx::PreInitialize(ix_accounts, de_ix_data))
            }
            [11] => {
                check_min_accounts_req(accounts_len, 18)?;
                let ix_accounts = SwapBaseOutIxAccounts {
                    token_program: ix.accounts[0].0.into(),
                    amm: ix.accounts[1].0.into(),
                    amm_authority: ix.accounts[2].0.into(),
                    amm_open_orders: ix.accounts[3].0.into(),
                    amm_target_orders: ix.accounts[4].0.into(),
                    pool_coin_token_account: ix.accounts[5].0.into(),
                    pool_pc_token_account: ix.accounts[6].0.into(),
                    serum_program: ix.accounts[7].0.into(),
                    serum_market: ix.accounts[8].0.into(),
                    serum_bids: ix.accounts[9].0.into(),
                    serum_asks: ix.accounts[10].0.into(),
                    serum_event_queue: ix.accounts[11].0.into(),
                    serum_coin_vault_account: ix.accounts[12].0.into(),
                    serum_pc_vault_account: ix.accounts[13].0.into(),
                    serum_vault_signer: ix.accounts[14].0.into(),
                    uer_source_token_account: ix.accounts[15].0.into(),
                    uer_destination_token_account: ix.accounts[16].0.into(),
                    user_source_owner: ix.accounts[17].0.into(),
                };
                let de_ix_data: SwapBaseOutIxData = BorshDeserialize::deserialize(&mut ix_data)?;
                Ok(RaydiumAmmProgramIx::SwapBaseOut(ix_accounts, de_ix_data))
            }
            [12] => {
                check_min_accounts_req(accounts_len, 8)?;
                let ix_accounts = SimulateInfoIxAccounts {
                    amm: ix.accounts[0].0.into(),
                    amm_authority: ix.accounts[1].0.into(),
                    amm_open_orders: ix.accounts[2].0.into(),
                    pool_coin_token_account: ix.accounts[3].0.into(),
                    pool_pc_token_account: ix.accounts[4].0.into(),
                    lp_mint_address: ix.accounts[5].0.into(),
                    serum_market: ix.accounts[6].0.into(),
                    serum_event_queue: ix.accounts[7].0.into(),
                };
                let de_ix_data: SimulateInfoIxData = BorshDeserialize::deserialize(&mut ix_data)?;
                Ok(RaydiumAmmProgramIx::SimulateInfo(ix_accounts, de_ix_data))
            }
            [13] => {
                check_min_accounts_req(accounts_len, 17)?;
                let ix_accounts = AdminCancelOrdersIxAccounts {
                    token_program: ix.accounts[0].0.into(),
                    amm: ix.accounts[1].0.into(),
                    amm_authority: ix.accounts[2].0.into(),
                    amm_open_orders: ix.accounts[3].0.into(),
                    amm_target_orders: ix.accounts[4].0.into(),
                    pool_coin_token_account: ix.accounts[5].0.into(),
                    pool_pc_token_account: ix.accounts[6].0.into(),
                    amm_owner_account: ix.accounts[7].0.into(),
                    amm_config: ix.accounts[8].0.into(),
                    serum_program: ix.accounts[9].0.into(),
                    serum_market: ix.accounts[10].0.into(),
                    serum_coin_vault_account: ix.accounts[11].0.into(),
                    serum_pc_vault_account: ix.accounts[12].0.into(),
                    serum_vault_signer: ix.accounts[13].0.into(),
                    serum_event_q: ix.accounts[14].0.into(),
                    serum_bids: ix.accounts[15].0.into(),
                    serum_asks: ix.accounts[16].0.into(),
                };
                let de_ix_data: AdminCancelOrdersIxData =
                    BorshDeserialize::deserialize(&mut ix_data)?;
                Ok(RaydiumAmmProgramIx::AdminCancelOrders(
                    ix_accounts,
                    de_ix_data,
                ))
            }
            [14] => {
                check_min_accounts_req(accounts_len, 5)?;
                let ix_accounts = CreateConfigAccountIxAccounts {
                    admin: ix.accounts[0].0.into(),
                    amm_config: ix.accounts[1].0.into(),
                    owner: ix.accounts[2].0.into(),
                    system_program: ix.accounts[3].0.into(),
                    rent: ix.accounts[4].0.into(),
                };
                Ok(RaydiumAmmProgramIx::CreateConfigAccount(ix_accounts))
            }
            [15] => {
                check_min_accounts_req(accounts_len, 2)?;
                let ix_accounts = UpdateConfigAccountIxAccounts {
                    admin: ix.accounts[0].0.into(),
                    amm_config: ix.accounts[1].0.into(),
                };
                let de_ix_data: UpdateConfigAccountIxData =
                    BorshDeserialize::deserialize(&mut ix_data)?;
                Ok(RaydiumAmmProgramIx::UpdateConfigAccount(
                    ix_accounts,
                    de_ix_data,
                ))
            }
            _ => Err(yellowstone_vixen_core::ParseError::from(
                "Invalid Instruction discriminator".to_owned(),
            )),
        };

        #[cfg(feature = "tracing")]
        match &ix {
            Ok(ix) => {
                tracing::info!(
                    name: "correctly_parsed_instruction",
                    name = "ix_update",
                    program = ID.to_string(),
                    ix = ix.to_string()
                );
            }
            Err(e) => {
                tracing::info!(
                    name: "incorrectly_parsed_instruction",
                    name = "ix_update",
                    program = ID.to_string(),
                    ix = "error",
                    discriminator = ?ix_discriminator,
                    error = ?e
                );
            }
        }

        ix
    }
}

pub fn check_min_accounts_req(
    actual: usize,
    expected: usize,
) -> yellowstone_vixen_core::ParseResult<()> {
    if actual < expected {
        Err(yellowstone_vixen_core::ParseError::from(format!(
            "Too few accounts provided: expected {expected}, got {actual}"
        )))
    } else {
        Ok(())
    }
}

// #[cfg(feature = "proto")]
mod proto_parser {
    use super::{InstructionParser, RaydiumAmmProgramIx};
    use crate::{proto_def, proto_helpers::proto_types_parsers::IntoProto};
    use yellowstone_vixen_core::proto::ParseProto;

    use super::InitializeIxAccounts;
    impl IntoProto<proto_def::InitializeIxAccounts> for InitializeIxAccounts {
        fn into_proto(self) -> proto_def::InitializeIxAccounts {
            proto_def::InitializeIxAccounts {
                token_program: self.token_program.to_string(),
                system_program: self.system_program.to_string(),
                rent: self.rent.to_string(),
                amm: self.amm.to_string(),
                amm_authority: self.amm_authority.to_string(),
                amm_open_orders: self.amm_open_orders.to_string(),
                lp_mint_address: self.lp_mint_address.to_string(),
                coin_mint_address: self.coin_mint_address.to_string(),
                pc_mint_address: self.pc_mint_address.to_string(),
                pool_coin_token_account: self.pool_coin_token_account.to_string(),
                pool_pc_token_account: self.pool_pc_token_account.to_string(),
                pool_withdraw_queue: self.pool_withdraw_queue.to_string(),
                pool_target_orders_account: self.pool_target_orders_account.to_string(),
                user_lp_token_account: self.user_lp_token_account.to_string(),
                pool_temp_lp_token_account: self.pool_temp_lp_token_account.to_string(),
                serum_program: self.serum_program.to_string(),
                serum_market: self.serum_market.to_string(),
                user_wallet: self.user_wallet.to_string(),
            }
        }
    }
    use super::InitializeIxData;
    impl IntoProto<proto_def::InitializeIxData> for InitializeIxData {
        fn into_proto(self) -> proto_def::InitializeIxData {
            proto_def::InitializeIxData {
                nonce: self.nonce.into(),
                open_time: self.open_time,
            }
        }
    }
    use super::Initialize2IxAccounts;
    impl IntoProto<proto_def::Initialize2IxAccounts> for Initialize2IxAccounts {
        fn into_proto(self) -> proto_def::Initialize2IxAccounts {
            proto_def::Initialize2IxAccounts {
                token_program: self.token_program.to_string(),
                spl_associated_token_account: self.spl_associated_token_account.to_string(),
                system_program: self.system_program.to_string(),
                rent: self.rent.to_string(),
                amm: self.amm.to_string(),
                amm_authority: self.amm_authority.to_string(),
                amm_open_orders: self.amm_open_orders.to_string(),
                lp_mint: self.lp_mint.to_string(),
                coin_mint: self.coin_mint.to_string(),
                pc_mint: self.pc_mint.to_string(),
                pool_coin_token_account: self.pool_coin_token_account.to_string(),
                pool_pc_token_account: self.pool_pc_token_account.to_string(),
                pool_withdraw_queue: self.pool_withdraw_queue.to_string(),
                amm_target_orders: self.amm_target_orders.to_string(),
                pool_temp_lp: self.pool_temp_lp.to_string(),
                serum_program: self.serum_program.to_string(),
                serum_market: self.serum_market.to_string(),
                user_wallet: self.user_wallet.to_string(),
                user_token_coin: self.user_token_coin.to_string(),
                user_token_pc: self.user_token_pc.to_string(),
                user_lp_token_account: self.user_lp_token_account.to_string(),
            }
        }
    }
    use super::Initialize2IxData;
    impl IntoProto<proto_def::Initialize2IxData> for Initialize2IxData {
        fn into_proto(self) -> proto_def::Initialize2IxData {
            proto_def::Initialize2IxData {
                nonce: self.nonce.into(),
                open_time: self.open_time,
                init_pc_amount: self.init_pc_amount,
                init_coin_amount: self.init_coin_amount,
            }
        }
    }
    use super::MonitorStepIxAccounts;
    impl IntoProto<proto_def::MonitorStepIxAccounts> for MonitorStepIxAccounts {
        fn into_proto(self) -> proto_def::MonitorStepIxAccounts {
            proto_def::MonitorStepIxAccounts {
                token_program: self.token_program.to_string(),
                rent: self.rent.to_string(),
                clock: self.clock.to_string(),
                amm: self.amm.to_string(),
                amm_authority: self.amm_authority.to_string(),
                amm_open_orders: self.amm_open_orders.to_string(),
                amm_target_orders: self.amm_target_orders.to_string(),
                pool_coin_token_account: self.pool_coin_token_account.to_string(),
                pool_pc_token_account: self.pool_pc_token_account.to_string(),
                pool_withdraw_queue: self.pool_withdraw_queue.to_string(),
                serum_program: self.serum_program.to_string(),
                serum_market: self.serum_market.to_string(),
                serum_coin_vault_account: self.serum_coin_vault_account.to_string(),
                serum_pc_vault_account: self.serum_pc_vault_account.to_string(),
                serum_vault_signer: self.serum_vault_signer.to_string(),
                serum_req_q: self.serum_req_q.to_string(),
                serum_event_q: self.serum_event_q.to_string(),
                serum_bids: self.serum_bids.to_string(),
                serum_asks: self.serum_asks.to_string(),
            }
        }
    }
    use super::MonitorStepIxData;
    impl IntoProto<proto_def::MonitorStepIxData> for MonitorStepIxData {
        fn into_proto(self) -> proto_def::MonitorStepIxData {
            proto_def::MonitorStepIxData {
                plan_order_limit: self.plan_order_limit.into(),
                place_order_limit: self.place_order_limit.into(),
                cancel_order_limit: self.cancel_order_limit.into(),
            }
        }
    }
    use super::DepositIxAccounts;
    impl IntoProto<proto_def::DepositIxAccounts> for DepositIxAccounts {
        fn into_proto(self) -> proto_def::DepositIxAccounts {
            proto_def::DepositIxAccounts {
                token_program: self.token_program.to_string(),
                amm: self.amm.to_string(),
                amm_authority: self.amm_authority.to_string(),
                amm_open_orders: self.amm_open_orders.to_string(),
                amm_target_orders: self.amm_target_orders.to_string(),
                lp_mint_address: self.lp_mint_address.to_string(),
                pool_coin_token_account: self.pool_coin_token_account.to_string(),
                pool_pc_token_account: self.pool_pc_token_account.to_string(),
                serum_market: self.serum_market.to_string(),
                user_coin_token_account: self.user_coin_token_account.to_string(),
                user_pc_token_account: self.user_pc_token_account.to_string(),
                user_lp_token_account: self.user_lp_token_account.to_string(),
                user_owner: self.user_owner.to_string(),
                serum_event_queue: self.serum_event_queue.to_string(),
            }
        }
    }
    use super::DepositIxData;
    impl IntoProto<proto_def::DepositIxData> for DepositIxData {
        fn into_proto(self) -> proto_def::DepositIxData {
            proto_def::DepositIxData {
                max_coin_amount: self.max_coin_amount,
                max_pc_amount: self.max_pc_amount,
                base_side: self.base_side,
            }
        }
    }
    use super::WithdrawIxAccounts;
    impl IntoProto<proto_def::WithdrawIxAccounts> for WithdrawIxAccounts {
        fn into_proto(self) -> proto_def::WithdrawIxAccounts {
            proto_def::WithdrawIxAccounts {
                token_program: self.token_program.to_string(),
                amm: self.amm.to_string(),
                amm_authority: self.amm_authority.to_string(),
                amm_open_orders: self.amm_open_orders.to_string(),
                amm_target_orders: self.amm_target_orders.to_string(),
                lp_mint_address: self.lp_mint_address.to_string(),
                pool_coin_token_account: self.pool_coin_token_account.to_string(),
                pool_pc_token_account: self.pool_pc_token_account.to_string(),
                pool_withdraw_queue: self.pool_withdraw_queue.to_string(),
                pool_temp_lp_token_account: self.pool_temp_lp_token_account.to_string(),
                serum_program: self.serum_program.to_string(),
                serum_market: self.serum_market.to_string(),
                serum_coin_vault_account: self.serum_coin_vault_account.to_string(),
                serum_pc_vault_account: self.serum_pc_vault_account.to_string(),
                serum_vault_signer: self.serum_vault_signer.to_string(),
                user_lp_token_account: self.user_lp_token_account.to_string(),
                uer_coin_token_account: self.uer_coin_token_account.to_string(),
                uer_pc_token_account: self.uer_pc_token_account.to_string(),
                user_owner: self.user_owner.to_string(),
                serum_event_q: self.serum_event_q.to_string(),
                serum_bids: self.serum_bids.to_string(),
                serum_asks: self.serum_asks.to_string(),
            }
        }
    }
    use super::WithdrawIxData;
    impl IntoProto<proto_def::WithdrawIxData> for WithdrawIxData {
        fn into_proto(self) -> proto_def::WithdrawIxData {
            proto_def::WithdrawIxData {
                amount: self.amount,
            }
        }
    }
    use super::MigrateToOpenBookIxAccounts;
    impl IntoProto<proto_def::MigrateToOpenBookIxAccounts> for MigrateToOpenBookIxAccounts {
        fn into_proto(self) -> proto_def::MigrateToOpenBookIxAccounts {
            proto_def::MigrateToOpenBookIxAccounts {
                token_program: self.token_program.to_string(),
                system_program: self.system_program.to_string(),
                rent: self.rent.to_string(),
                amm: self.amm.to_string(),
                amm_authority: self.amm_authority.to_string(),
                amm_open_orders: self.amm_open_orders.to_string(),
                amm_token_coin: self.amm_token_coin.to_string(),
                amm_token_pc: self.amm_token_pc.to_string(),
                amm_target_orders: self.amm_target_orders.to_string(),
                serum_program: self.serum_program.to_string(),
                serum_market: self.serum_market.to_string(),
                serum_bids: self.serum_bids.to_string(),
                serum_asks: self.serum_asks.to_string(),
                serum_event_queue: self.serum_event_queue.to_string(),
                serum_coin_vault: self.serum_coin_vault.to_string(),
                serum_pc_vault: self.serum_pc_vault.to_string(),
                serum_vault_signer: self.serum_vault_signer.to_string(),
                new_amm_open_orders: self.new_amm_open_orders.to_string(),
                new_serum_program: self.new_serum_program.to_string(),
                new_serum_market: self.new_serum_market.to_string(),
                admin: self.admin.to_string(),
            }
        }
    }
    use super::SetParamsIxAccounts;
    impl IntoProto<proto_def::SetParamsIxAccounts> for SetParamsIxAccounts {
        fn into_proto(self) -> proto_def::SetParamsIxAccounts {
            proto_def::SetParamsIxAccounts {
                token_program: self.token_program.to_string(),
                amm: self.amm.to_string(),
                amm_authority: self.amm_authority.to_string(),
                amm_open_orders: self.amm_open_orders.to_string(),
                amm_target_orders: self.amm_target_orders.to_string(),
                amm_coin_vault: self.amm_coin_vault.to_string(),
                amm_pc_vault: self.amm_pc_vault.to_string(),
                serum_program: self.serum_program.to_string(),
                serum_market: self.serum_market.to_string(),
                serum_coin_vault: self.serum_coin_vault.to_string(),
                serum_pc_vault: self.serum_pc_vault.to_string(),
                serum_vault_signer: self.serum_vault_signer.to_string(),
                serum_event_queue: self.serum_event_queue.to_string(),
                serum_bids: self.serum_bids.to_string(),
                serum_asks: self.serum_asks.to_string(),
                amm_admin_account: self.amm_admin_account.to_string(),
            }
        }
    }
    use super::SetParamsIxData;
    impl IntoProto<proto_def::SetParamsIxData> for SetParamsIxData {
        fn into_proto(self) -> proto_def::SetParamsIxData {
            proto_def::SetParamsIxData {
                param: self.param.into(),
                value: self.value,
                new_pubkey: self.new_pubkey.map(|x| x.to_string()),
                fees: self.fees.map(|x| x.into_proto()),
                last_order_distance: self.last_order_distance.map(|x| x.into_proto()),
                need_take_amounts: self.need_take_amounts.map(|x| x.into_proto()),
            }
        }
    }
    use super::WithdrawPnlIxAccounts;
    impl IntoProto<proto_def::WithdrawPnlIxAccounts> for WithdrawPnlIxAccounts {
        fn into_proto(self) -> proto_def::WithdrawPnlIxAccounts {
            proto_def::WithdrawPnlIxAccounts {
                token_program: self.token_program.to_string(),
                amm: self.amm.to_string(),
                amm_config: self.amm_config.to_string(),
                amm_authority: self.amm_authority.to_string(),
                amm_open_orders: self.amm_open_orders.to_string(),
                pool_coin_token_account: self.pool_coin_token_account.to_string(),
                pool_pc_token_account: self.pool_pc_token_account.to_string(),
                coin_pnl_token_account: self.coin_pnl_token_account.to_string(),
                pc_pnl_token_account: self.pc_pnl_token_account.to_string(),
                pnl_owner_account: self.pnl_owner_account.to_string(),
                amm_target_orders: self.amm_target_orders.to_string(),
                serum_program: self.serum_program.to_string(),
                serum_market: self.serum_market.to_string(),
                serum_event_queue: self.serum_event_queue.to_string(),
                serum_coin_vault_account: self.serum_coin_vault_account.to_string(),
                serum_pc_vault_account: self.serum_pc_vault_account.to_string(),
                serum_vault_signer: self.serum_vault_signer.to_string(),
            }
        }
    }
    use super::WithdrawSrmIxAccounts;
    impl IntoProto<proto_def::WithdrawSrmIxAccounts> for WithdrawSrmIxAccounts {
        fn into_proto(self) -> proto_def::WithdrawSrmIxAccounts {
            proto_def::WithdrawSrmIxAccounts {
                token_program: self.token_program.to_string(),
                amm: self.amm.to_string(),
                amm_owner_account: self.amm_owner_account.to_string(),
                amm_authority: self.amm_authority.to_string(),
                srm_token: self.srm_token.to_string(),
                dest_srm_token: self.dest_srm_token.to_string(),
            }
        }
    }
    use super::WithdrawSrmIxData;
    impl IntoProto<proto_def::WithdrawSrmIxData> for WithdrawSrmIxData {
        fn into_proto(self) -> proto_def::WithdrawSrmIxData {
            proto_def::WithdrawSrmIxData {
                amount: self.amount,
            }
        }
    }
    use super::SwapBaseInIxAccounts;
    impl IntoProto<proto_def::SwapBaseInIxAccounts> for SwapBaseInIxAccounts {
        fn into_proto(self) -> proto_def::SwapBaseInIxAccounts {
            proto_def::SwapBaseInIxAccounts {
                token_program: self.token_program.to_string(),
                amm: self.amm.to_string(),
                amm_authority: self.amm_authority.to_string(),
                amm_open_orders: self.amm_open_orders.to_string(),
                amm_target_orders: self.amm_target_orders.to_string(),
                pool_coin_token_account: self.pool_coin_token_account.to_string(),
                pool_pc_token_account: self.pool_pc_token_account.to_string(),
                serum_program: self.serum_program.to_string(),
                serum_market: self.serum_market.to_string(),
                serum_bids: self.serum_bids.to_string(),
                serum_asks: self.serum_asks.to_string(),
                serum_event_queue: self.serum_event_queue.to_string(),
                serum_coin_vault_account: self.serum_coin_vault_account.to_string(),
                serum_pc_vault_account: self.serum_pc_vault_account.to_string(),
                serum_vault_signer: self.serum_vault_signer.to_string(),
                uer_source_token_account: self.uer_source_token_account.to_string(),
                uer_destination_token_account: self.uer_destination_token_account.to_string(),
                user_source_owner: self.user_source_owner.to_string(),
            }
        }
    }
    use super::SwapBaseInIxData;
    impl IntoProto<proto_def::SwapBaseInIxData> for SwapBaseInIxData {
        fn into_proto(self) -> proto_def::SwapBaseInIxData {
            proto_def::SwapBaseInIxData {
                amount_in: self.amount_in,
                minimum_amount_out: self.minimum_amount_out,
            }
        }
    }
    use super::PreInitializeIxAccounts;
    impl IntoProto<proto_def::PreInitializeIxAccounts> for PreInitializeIxAccounts {
        fn into_proto(self) -> proto_def::PreInitializeIxAccounts {
            proto_def::PreInitializeIxAccounts {
                token_program: self.token_program.to_string(),
                system_program: self.system_program.to_string(),
                rent: self.rent.to_string(),
                amm_target_orders: self.amm_target_orders.to_string(),
                pool_withdraw_queue: self.pool_withdraw_queue.to_string(),
                amm_authority: self.amm_authority.to_string(),
                lp_mint_address: self.lp_mint_address.to_string(),
                coin_mint_address: self.coin_mint_address.to_string(),
                pc_mint_address: self.pc_mint_address.to_string(),
                pool_coin_token_account: self.pool_coin_token_account.to_string(),
                pool_pc_token_account: self.pool_pc_token_account.to_string(),
                pool_temp_lp_token_account: self.pool_temp_lp_token_account.to_string(),
                serum_market: self.serum_market.to_string(),
                user_wallet: self.user_wallet.to_string(),
            }
        }
    }
    use super::PreInitializeIxData;
    impl IntoProto<proto_def::PreInitializeIxData> for PreInitializeIxData {
        fn into_proto(self) -> proto_def::PreInitializeIxData {
            proto_def::PreInitializeIxData {
                nonce: self.nonce.into(),
            }
        }
    }
    use super::SwapBaseOutIxAccounts;
    impl IntoProto<proto_def::SwapBaseOutIxAccounts> for SwapBaseOutIxAccounts {
        fn into_proto(self) -> proto_def::SwapBaseOutIxAccounts {
            proto_def::SwapBaseOutIxAccounts {
                token_program: self.token_program.to_string(),
                amm: self.amm.to_string(),
                amm_authority: self.amm_authority.to_string(),
                amm_open_orders: self.amm_open_orders.to_string(),
                amm_target_orders: self.amm_target_orders.to_string(),
                pool_coin_token_account: self.pool_coin_token_account.to_string(),
                pool_pc_token_account: self.pool_pc_token_account.to_string(),
                serum_program: self.serum_program.to_string(),
                serum_market: self.serum_market.to_string(),
                serum_bids: self.serum_bids.to_string(),
                serum_asks: self.serum_asks.to_string(),
                serum_event_queue: self.serum_event_queue.to_string(),
                serum_coin_vault_account: self.serum_coin_vault_account.to_string(),
                serum_pc_vault_account: self.serum_pc_vault_account.to_string(),
                serum_vault_signer: self.serum_vault_signer.to_string(),
                uer_source_token_account: self.uer_source_token_account.to_string(),
                uer_destination_token_account: self.uer_destination_token_account.to_string(),
                user_source_owner: self.user_source_owner.to_string(),
            }
        }
    }
    use super::SwapBaseOutIxData;
    impl IntoProto<proto_def::SwapBaseOutIxData> for SwapBaseOutIxData {
        fn into_proto(self) -> proto_def::SwapBaseOutIxData {
            proto_def::SwapBaseOutIxData {
                max_amount_in: self.max_amount_in,
                amount_out: self.amount_out,
            }
        }
    }
    use super::SimulateInfoIxAccounts;
    impl IntoProto<proto_def::SimulateInfoIxAccounts> for SimulateInfoIxAccounts {
        fn into_proto(self) -> proto_def::SimulateInfoIxAccounts {
            proto_def::SimulateInfoIxAccounts {
                amm: self.amm.to_string(),
                amm_authority: self.amm_authority.to_string(),
                amm_open_orders: self.amm_open_orders.to_string(),
                pool_coin_token_account: self.pool_coin_token_account.to_string(),
                pool_pc_token_account: self.pool_pc_token_account.to_string(),
                lp_mint_address: self.lp_mint_address.to_string(),
                serum_market: self.serum_market.to_string(),
                serum_event_queue: self.serum_event_queue.to_string(),
            }
        }
    }
    use super::SimulateInfoIxData;
    impl IntoProto<proto_def::SimulateInfoIxData> for SimulateInfoIxData {
        fn into_proto(self) -> proto_def::SimulateInfoIxData {
            proto_def::SimulateInfoIxData {
                param: self.param.into(),
                swap_base_in_value: self.swap_base_in_value.map(|x| x.into_proto()),
                swap_base_out_value: self.swap_base_out_value.map(|x| x.into_proto()),
            }
        }
    }
    use super::AdminCancelOrdersIxAccounts;
    impl IntoProto<proto_def::AdminCancelOrdersIxAccounts> for AdminCancelOrdersIxAccounts {
        fn into_proto(self) -> proto_def::AdminCancelOrdersIxAccounts {
            proto_def::AdminCancelOrdersIxAccounts {
                token_program: self.token_program.to_string(),
                amm: self.amm.to_string(),
                amm_authority: self.amm_authority.to_string(),
                amm_open_orders: self.amm_open_orders.to_string(),
                amm_target_orders: self.amm_target_orders.to_string(),
                pool_coin_token_account: self.pool_coin_token_account.to_string(),
                pool_pc_token_account: self.pool_pc_token_account.to_string(),
                amm_owner_account: self.amm_owner_account.to_string(),
                amm_config: self.amm_config.to_string(),
                serum_program: self.serum_program.to_string(),
                serum_market: self.serum_market.to_string(),
                serum_coin_vault_account: self.serum_coin_vault_account.to_string(),
                serum_pc_vault_account: self.serum_pc_vault_account.to_string(),
                serum_vault_signer: self.serum_vault_signer.to_string(),
                serum_event_q: self.serum_event_q.to_string(),
                serum_bids: self.serum_bids.to_string(),
                serum_asks: self.serum_asks.to_string(),
            }
        }
    }
    use super::AdminCancelOrdersIxData;
    impl IntoProto<proto_def::AdminCancelOrdersIxData> for AdminCancelOrdersIxData {
        fn into_proto(self) -> proto_def::AdminCancelOrdersIxData {
            proto_def::AdminCancelOrdersIxData {
                limit: self.limit.into(),
            }
        }
    }
    use super::CreateConfigAccountIxAccounts;
    impl IntoProto<proto_def::CreateConfigAccountIxAccounts> for CreateConfigAccountIxAccounts {
        fn into_proto(self) -> proto_def::CreateConfigAccountIxAccounts {
            proto_def::CreateConfigAccountIxAccounts {
                admin: self.admin.to_string(),
                amm_config: self.amm_config.to_string(),
                owner: self.owner.to_string(),
                system_program: self.system_program.to_string(),
                rent: self.rent.to_string(),
            }
        }
    }
    use super::UpdateConfigAccountIxAccounts;
    impl IntoProto<proto_def::UpdateConfigAccountIxAccounts> for UpdateConfigAccountIxAccounts {
        fn into_proto(self) -> proto_def::UpdateConfigAccountIxAccounts {
            proto_def::UpdateConfigAccountIxAccounts {
                admin: self.admin.to_string(),
                amm_config: self.amm_config.to_string(),
            }
        }
    }
    use super::UpdateConfigAccountIxData;
    impl IntoProto<proto_def::UpdateConfigAccountIxData> for UpdateConfigAccountIxData {
        fn into_proto(self) -> proto_def::UpdateConfigAccountIxData {
            proto_def::UpdateConfigAccountIxData {
                param: self.param.into(),
                owner: self.owner.to_string(),
            }
        }
    }

    impl IntoProto<proto_def::ProgramIxs> for RaydiumAmmProgramIx {
        fn into_proto(self) -> proto_def::ProgramIxs {
            match self {
                RaydiumAmmProgramIx::Initialize(acc, data) => proto_def::ProgramIxs {
                    ix_oneof: Some(proto_def::program_ixs::IxOneof::Initialize(
                        proto_def::InitializeIx {
                            accounts: Some(acc.into_proto()),
                            data: Some(data.into_proto()),
                        },
                    )),
                },
                RaydiumAmmProgramIx::Initialize2(acc, data) => proto_def::ProgramIxs {
                    ix_oneof: Some(proto_def::program_ixs::IxOneof::Initialize2(
                        proto_def::Initialize2Ix {
                            accounts: Some(acc.into_proto()),
                            data: Some(data.into_proto()),
                        },
                    )),
                },
                RaydiumAmmProgramIx::MonitorStep(acc, data) => proto_def::ProgramIxs {
                    ix_oneof: Some(proto_def::program_ixs::IxOneof::MonitorStep(
                        proto_def::MonitorStepIx {
                            accounts: Some(acc.into_proto()),
                            data: Some(data.into_proto()),
                        },
                    )),
                },
                RaydiumAmmProgramIx::Deposit(acc, data) => proto_def::ProgramIxs {
                    ix_oneof: Some(proto_def::program_ixs::IxOneof::Deposit(
                        proto_def::DepositIx {
                            accounts: Some(acc.into_proto()),
                            data: Some(data.into_proto()),
                        },
                    )),
                },
                RaydiumAmmProgramIx::Withdraw(acc, data) => proto_def::ProgramIxs {
                    ix_oneof: Some(proto_def::program_ixs::IxOneof::Withdraw(
                        proto_def::WithdrawIx {
                            accounts: Some(acc.into_proto()),
                            data: Some(data.into_proto()),
                        },
                    )),
                },
                RaydiumAmmProgramIx::MigrateToOpenBook(acc) => proto_def::ProgramIxs {
                    ix_oneof: Some(proto_def::program_ixs::IxOneof::MigrateToOpenBook(
                        proto_def::MigrateToOpenBookIx {
                            accounts: Some(acc.into_proto()),
                        },
                    )),
                },
                RaydiumAmmProgramIx::SetParams(acc, data) => proto_def::ProgramIxs {
                    ix_oneof: Some(proto_def::program_ixs::IxOneof::SetParams(
                        proto_def::SetParamsIx {
                            accounts: Some(acc.into_proto()),
                            data: Some(data.into_proto()),
                        },
                    )),
                },
                RaydiumAmmProgramIx::WithdrawPnl(acc) => proto_def::ProgramIxs {
                    ix_oneof: Some(proto_def::program_ixs::IxOneof::WithdrawPnl(
                        proto_def::WithdrawPnlIx {
                            accounts: Some(acc.into_proto()),
                        },
                    )),
                },
                RaydiumAmmProgramIx::WithdrawSrm(acc, data) => proto_def::ProgramIxs {
                    ix_oneof: Some(proto_def::program_ixs::IxOneof::WithdrawSrm(
                        proto_def::WithdrawSrmIx {
                            accounts: Some(acc.into_proto()),
                            data: Some(data.into_proto()),
                        },
                    )),
                },
                RaydiumAmmProgramIx::SwapBaseIn(acc, data) => proto_def::ProgramIxs {
                    ix_oneof: Some(proto_def::program_ixs::IxOneof::SwapBaseIn(
                        proto_def::SwapBaseInIx {
                            accounts: Some(acc.into_proto()),
                            data: Some(data.into_proto()),
                        },
                    )),
                },
                RaydiumAmmProgramIx::PreInitialize(acc, data) => proto_def::ProgramIxs {
                    ix_oneof: Some(proto_def::program_ixs::IxOneof::PreInitialize(
                        proto_def::PreInitializeIx {
                            accounts: Some(acc.into_proto()),
                            data: Some(data.into_proto()),
                        },
                    )),
                },
                RaydiumAmmProgramIx::SwapBaseOut(acc, data) => proto_def::ProgramIxs {
                    ix_oneof: Some(proto_def::program_ixs::IxOneof::SwapBaseOut(
                        proto_def::SwapBaseOutIx {
                            accounts: Some(acc.into_proto()),
                            data: Some(data.into_proto()),
                        },
                    )),
                },
                RaydiumAmmProgramIx::SimulateInfo(acc, data) => proto_def::ProgramIxs {
                    ix_oneof: Some(proto_def::program_ixs::IxOneof::SimulateInfo(
                        proto_def::SimulateInfoIx {
                            accounts: Some(acc.into_proto()),
                            data: Some(data.into_proto()),
                        },
                    )),
                },
                RaydiumAmmProgramIx::AdminCancelOrders(acc, data) => proto_def::ProgramIxs {
                    ix_oneof: Some(proto_def::program_ixs::IxOneof::AdminCancelOrders(
                        proto_def::AdminCancelOrdersIx {
                            accounts: Some(acc.into_proto()),
                            data: Some(data.into_proto()),
                        },
                    )),
                },
                RaydiumAmmProgramIx::CreateConfigAccount(acc) => proto_def::ProgramIxs {
                    ix_oneof: Some(proto_def::program_ixs::IxOneof::CreateConfigAccount(
                        proto_def::CreateConfigAccountIx {
                            accounts: Some(acc.into_proto()),
                        },
                    )),
                },
                RaydiumAmmProgramIx::UpdateConfigAccount(acc, data) => proto_def::ProgramIxs {
                    ix_oneof: Some(proto_def::program_ixs::IxOneof::UpdateConfigAccount(
                        proto_def::UpdateConfigAccountIx {
                            accounts: Some(acc.into_proto()),
                            data: Some(data.into_proto()),
                        },
                    )),
                },
            }
        }
    }

    impl ParseProto for InstructionParser {
        type Message = proto_def::ProgramIxs;

        fn output_into_message(value: Self::Output) -> Self::Message {
            value.into_proto()
        }
    }
}
