Skip to main content

riptide_amm/gpa/
market.rs

1use anyhow::Result;
2use solana_client::{
3    rpc_client::RpcClient,
4    rpc_filter::{Memcmp, RpcFilterType},
5};
6use solana_pubkey::Pubkey;
7
8use crate::{generated::shared::DecodedAccount, Market, MARKET_DISCRIMINATOR, RIPTIDE_ID};
9
10use crate::fetch_decoded_program_accounts;
11
12#[derive(Debug, Clone)]
13pub enum StrategyFilter {
14    Authority(Pubkey),
15    Updater(Pubkey),
16    MintA(Pubkey),
17    MintB(Pubkey),
18}
19
20impl From<StrategyFilter> for RpcFilterType {
21    fn from(val: StrategyFilter) -> Self {
22        match val {
23            StrategyFilter::Authority(address) => {
24                RpcFilterType::Memcmp(Memcmp::new_raw_bytes(8, address.to_bytes().to_vec()))
25            }
26            StrategyFilter::Updater(address) => {
27                RpcFilterType::Memcmp(Memcmp::new_raw_bytes(40, address.to_bytes().to_vec()))
28            }
29            StrategyFilter::MintA(address) => {
30                RpcFilterType::Memcmp(Memcmp::new_raw_bytes(72, address.to_bytes().to_vec()))
31            }
32            StrategyFilter::MintB(address) => {
33                RpcFilterType::Memcmp(Memcmp::new_raw_bytes(104, address.to_bytes().to_vec()))
34            }
35        }
36    }
37}
38
39pub fn fetch_all_strategy_with_filter(
40    rpc: &RpcClient,
41    filters: Vec<StrategyFilter>,
42) -> Result<Vec<DecodedAccount<Market>>> {
43    let mut filters: Vec<RpcFilterType> = filters.into_iter().map(|filter| filter.into()).collect();
44    filters.push(RpcFilterType::Memcmp(Memcmp::new_raw_bytes(
45        0,
46        vec![MARKET_DISCRIMINATOR as u8],
47    )));
48    fetch_decoded_program_accounts(rpc, filters, RIPTIDE_ID)
49}
50
51#[cfg(test)]
52mod tests {
53    use solana_pubkey::pubkey;
54
55    use crate::AccountDiscriminator;
56
57    use super::*;
58
59    #[test]
60    fn test_fetch_all_strategy_with_filter() {
61        let strategy = Market {
62            discriminator: AccountDiscriminator::Market,
63            authority: pubkey!("BGDWUVagGJHzF4XmT3iYMAkgjpaWq8YYAqkhwiJFnXqf"),
64            updater: pubkey!("5bAXtoqFDCC4H9gkiS8zPAwXfFo6g4qmCWhT8AeZmBnS"),
65            mint_a: pubkey!("8tGnYJSpzCNgKs4G4iNMPBfMGLEVsTu9ofapntcMgrrM"),
66            mint_b: pubkey!("6yuYbHEz9ybDnZAuXeC6yCxHETtUspSsHfkMnzdY5mqS"),
67            bump: [0; 1],
68            id: 0,
69            sequence: 0,
70            valid_until: 0,
71            oracle: [0; 512],
72            padding1: [0; 2],
73            padding2: [0; 360],
74        };
75        let strategy_data = borsh::to_vec(&strategy).unwrap();
76        let filters: Vec<RpcFilterType> = vec![
77            StrategyFilter::Authority(strategy.authority).into(),
78            StrategyFilter::MintA(strategy.mint_a).into(),
79            StrategyFilter::MintB(strategy.mint_b).into(),
80        ];
81        for filter in filters {
82            match filter {
83                RpcFilterType::Memcmp(memcmp) => {
84                    let offset = memcmp.offset();
85                    let actual = memcmp.bytes().unwrap().to_vec();
86                    let expected = strategy_data[offset..offset + actual.len()].to_vec();
87                    assert_eq!(actual, expected);
88                }
89                _ => panic!("Unexpected filter type"),
90            }
91        }
92    }
93}