manifest/program/instruction_builders/
batch_update_instruction.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#[cfg(feature = "certora")]
use crate::program::batch_update::{CancelOrderParams, PlaceOrderParams};
#[cfg(not(feature = "certora"))]
use crate::{
    program::{
        batch_update::{BatchUpdateParams, CancelOrderParams, PlaceOrderParams},
        ManifestInstruction,
    },
    validation::{get_global_address, get_global_vault_address, get_vault_address},
};
#[cfg(not(feature = "certora"))]
use borsh::BorshSerialize;
use hypertree::DataIndex;
#[cfg(feature = "certora")]
use solana_program::{instruction::Instruction, pubkey::Pubkey};
#[cfg(not(feature = "certora"))]
use solana_program::{
    instruction::{AccountMeta, Instruction},
    pubkey::Pubkey,
    system_program,
};

// Token programs are needed for global orders with token22. Only include if
// this is global or could match with global. Defaults to normal token program.
#[cfg(not(feature = "certora"))]
pub fn batch_update_instruction(
    market: &Pubkey,
    payer: &Pubkey,
    trader_index_hint: Option<DataIndex>,
    cancels: Vec<CancelOrderParams>,
    orders: Vec<PlaceOrderParams>,
    base_mint_opt: Option<Pubkey>,
    base_mint_token_program_opt: Option<Pubkey>,
    quote_mint_opt: Option<Pubkey>,
    quote_mint_token_program_opt: Option<Pubkey>,
) -> Instruction {
    let mut account_metas: Vec<AccountMeta> = vec![
        AccountMeta::new(*payer, true),
        AccountMeta::new(*market, false),
        AccountMeta::new_readonly(system_program::id(), false),
    ];
    for (mint_opt, token_program_opt) in [
        (base_mint_opt, base_mint_token_program_opt),
        (quote_mint_opt, quote_mint_token_program_opt),
    ] {
        if let Some(mint) = mint_opt {
            let (global, _) = get_global_address(&mint);
            let (global_vault, _) = get_global_vault_address(&mint);
            let (market_vault, _) = get_vault_address(market, &mint);
            let mut global_account_metas: Vec<AccountMeta> = vec![
                AccountMeta::new_readonly(mint, false),
                AccountMeta::new(global, false),
                AccountMeta::new(global_vault, false),
                AccountMeta::new(market_vault, false),
            ];
            if token_program_opt.is_none()
                || token_program_opt.is_some_and(|f| f == spl_token::id())
            {
                global_account_metas.push(AccountMeta::new_readonly(spl_token::id(), false));
            } else {
                global_account_metas.push(AccountMeta::new_readonly(spl_token_2022::id(), false));
            }
            account_metas.extend(global_account_metas);
        }
    }

    Instruction {
        program_id: crate::id(),
        accounts: account_metas,
        data: [
            ManifestInstruction::BatchUpdate.to_vec(),
            BatchUpdateParams::new(trader_index_hint, cancels, orders)
                .try_to_vec()
                .unwrap(),
        ]
        .concat(),
    }
}

#[cfg(feature = "certora")]
pub fn batch_update_instruction(
    _market: &Pubkey,
    _payer: &Pubkey,
    _trader_index_hint: Option<DataIndex>,
    _cancels: Vec<CancelOrderParams>,
    _orders: Vec<PlaceOrderParams>,
    _base_mint_opt: Option<Pubkey>,
    _base_mint_token_program_opt: Option<Pubkey>,
    _quote_mint_opt: Option<Pubkey>,
    _quote_mint_token_program_opt: Option<Pubkey>,
) -> Instruction {
    // Empty intentionally, just here so it compiles.
    todo!()
}