asset-agnostic-orderbook 1.0.1-alpha.3

Solana library enabling generic on-chain orderbooks
Documentation
use bytemuck::Pod;
use num_traits::FromPrimitive;
use solana_program::{account_info::AccountInfo, msg, program_error::ProgramError, pubkey::Pubkey};

use crate::{
    instruction::AgnosticOrderbookInstruction,
    state::orderbook::{CallbackInfo, OrderSummary},
};

use borsh::BorshDeserialize;

pub mod cancel_order;
pub mod close_market;
pub mod consume_events;
pub mod create_market;
pub mod mass_cancel_orders;
pub mod new_order;

pub fn process_instruction<C: Pod + BorshDeserialize + CallbackInfo + PartialEq>(
    program_id: &Pubkey,
    accounts: &[AccountInfo],
    instruction_data: &[u8],
) -> Result<Option<OrderSummary>, ProgramError>
where
    <C as CallbackInfo>::CallbackId: PartialEq,
{
    msg!("Beginning processing");
    let instruction =
        FromPrimitive::from_u8(instruction_data[0]).ok_or(ProgramError::InvalidInstructionData)?;
    let instruction_data = &instruction_data[1..];
    msg!("Instruction unpacked");

    match instruction {
        AgnosticOrderbookInstruction::CreateMarket => {
            msg!("Instruction: Create Market");
            let accounts = create_market::Accounts::parse(accounts)?;
            let params = create_market::Params::try_from_slice(instruction_data)
                .map_err(|_| ProgramError::InvalidInstructionData)?;
            create_market::process::<C>(program_id, accounts, params)?;
        }
        AgnosticOrderbookInstruction::NewOrder => {
            msg!("Instruction: New Order");
            let accounts = new_order::Accounts::parse(accounts)?;
            let params = new_order::Params::<C>::try_from_slice(instruction_data)
                .map_err(|_| ProgramError::InvalidInstructionData)?;
            return new_order::process(program_id, accounts, params).map(Some);
        }
        AgnosticOrderbookInstruction::ConsumeEvents => {
            msg!("Instruction: Consume Events");
            let accounts = consume_events::Accounts::parse(accounts)?;
            let params = consume_events::Params::try_from_slice(instruction_data)
                .map_err(|_| ProgramError::InvalidInstructionData)?;
            consume_events::process::<C>(program_id, accounts, params)?;
        }
        AgnosticOrderbookInstruction::CancelOrder => {
            msg!("Instruction: Cancel Order");
            let accounts = cancel_order::Accounts::parse(accounts)?;
            let params = cancel_order::Params::try_from_slice(instruction_data)
                .map_err(|_| ProgramError::InvalidInstructionData)?;
            return cancel_order::process::<C>(program_id, accounts, params).map(Some);
        }
        AgnosticOrderbookInstruction::CloseMarket => {
            msg!("Instruction: Close Market");
            let accounts = close_market::Accounts::parse(accounts)?;
            close_market::process::<C>(program_id, accounts, close_market::Params {})?;
        }
        AgnosticOrderbookInstruction::MassCancelOrders => {
            msg!("Instruction: Mass Cancel Orders");
            let accounts = mass_cancel_orders::Accounts::parse(accounts)?;
            let params = mass_cancel_orders::Params::try_from_slice(instruction_data)
                .map_err(|_| ProgramError::InvalidInstructionData)?;
            return mass_cancel_orders::process::<C>(program_id, accounts, params).map(Some);
        }
    }
    Ok(None)
}