riptide_amm/gpa/
market.rs1use anyhow::Result;
2use solana_address::Address;
3use solana_client::{
4 rpc_client::RpcClient,
5 rpc_filter::{Memcmp, RpcFilterType},
6};
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(Address),
15 Updater(Address),
16 MintA(Address),
17 MintB(Address),
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_address::address;
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: address!("BGDWUVagGJHzF4XmT3iYMAkgjpaWq8YYAqkhwiJFnXqf"),
64 updater: address!("5bAXtoqFDCC4H9gkiS8zPAwXfFo6g4qmCWhT8AeZmBnS"),
65 mint_a: address!("8tGnYJSpzCNgKs4G4iNMPBfMGLEVsTu9ofapntcMgrrM"),
66 mint_b: address!("6yuYbHEz9ybDnZAuXeC6yCxHETtUspSsHfkMnzdY5mqS"),
67 bump: [0; 1],
68 id: 0,
69 sequence: 0,
70 valid_until: 0,
71 oracle: [0; 512],
72 min_spread_guard_per_m: 0,
73 arb_penalty_per_m: 0,
74 jitodontfront_penalty_per_m: 0,
75 min_oracle_price_guard: 0,
76 max_oracle_price_guard: 0,
77 cu_penalty_multiplier: 0,
78 max_inventory_imbalance_guard_per_cent: 0,
79 padding1: [0; 12],
80 padding2: [0; 304],
81 };
82 let strategy_data = borsh::to_vec(&strategy).unwrap();
83 let filters: Vec<RpcFilterType> = vec![
84 StrategyFilter::Authority(strategy.authority).into(),
85 StrategyFilter::MintA(strategy.mint_a).into(),
86 StrategyFilter::MintB(strategy.mint_b).into(),
87 ];
88 for filter in filters {
89 match filter {
90 RpcFilterType::Memcmp(memcmp) => {
91 let offset = memcmp.offset();
92 let actual = memcmp.bytes().unwrap().to_vec();
93 let expected = strategy_data[offset..offset + actual.len()].to_vec();
94 assert_eq!(actual, expected);
95 }
96 _ => panic!("Unexpected filter type"),
97 }
98 }
99 }
100}