Skip to main content

sol_parser_sdk/accounts/
mod.rs

1pub mod nonce;
2pub mod program_ids;
3pub mod pumpswap;
4pub mod rpc_wallet;
5pub mod token;
6pub mod utils;
7use crate::core::events::EventMetadata;
8use crate::grpc::EventTypeFilter;
9use crate::DexEvent;
10pub use nonce::parse_nonce_account;
11use program_ids::*;
12pub use pumpswap::{
13    parse_global_config as parse_pumpswap_global_config, parse_pool as parse_pumpswap_pool,
14};
15pub use rpc_wallet::rpc_resolve_user_wallet_pubkey;
16pub use token::parse_token_account;
17pub use token::AccountData;
18pub use utils::*;
19
20pub fn parse_account_unified(
21    account: &AccountData,
22    metadata: EventMetadata,
23    event_type_filter: Option<&EventTypeFilter>,
24) -> Option<DexEvent> {
25    if account.data.is_empty() {
26        return None;
27    }
28
29    // Early filtering based on event type filter
30    if let Some(filter) = event_type_filter {
31        if let Some(ref include_only) = filter.include_only {
32            // Check if any of the account event types are in the include list
33            let should_parse = include_only.iter().any(|t| {
34                use crate::grpc::EventType;
35                matches!(
36                    t,
37                    EventType::TokenAccount
38                        | EventType::NonceAccount
39                        | EventType::AccountPumpFunGlobal
40                        | EventType::AccountPumpSwapGlobalConfig
41                        | EventType::AccountPumpSwapPool
42                )
43            });
44            if !should_parse {
45                return None;
46            }
47        }
48    }
49
50    if account.owner == PUMPSWAP_PROGRAM_ID {
51        if let Some(filter) = event_type_filter {
52            if filter.should_include(crate::grpc::EventType::AccountPumpSwapGlobalConfig)
53                || filter.should_include(crate::grpc::EventType::AccountPumpSwapPool)
54            {
55                let event = parse_pumpswap_account(account, metadata.clone());
56                if event.is_some() {
57                    return event;
58                }
59            }
60        }
61    }
62    if account.owner == crate::grpc::program_ids::PUMPFUN_PROGRAM {
63        if let Some(filter) = event_type_filter {
64            if filter.should_include(crate::grpc::EventType::AccountPumpFunGlobal) {
65                let event = parse_pumpfun_account(account, metadata.clone());
66                if event.is_some() {
67                    return event;
68                }
69            }
70        }
71    }
72    if nonce::is_nonce_account(&account.data) {
73        // Check filter for NonceAccount specifically
74        if let Some(filter) = event_type_filter {
75            if !filter.should_include(crate::grpc::EventType::NonceAccount) {
76                return None;
77            }
78        }
79        return parse_nonce_account(account, metadata);
80    }
81    // Parse token account (includes both TokenAccount and TokenInfo)
82    if let Some(filter) = event_type_filter {
83        let includes_token = filter.should_include(crate::grpc::EventType::TokenAccount);
84        if !includes_token {
85            return None;
86        }
87    }
88    return parse_token_account(account, metadata);
89}
90
91fn parse_pumpswap_account(account: &AccountData, metadata: EventMetadata) -> Option<DexEvent> {
92    // 检查 discriminator 以确定账户类型
93    if pumpswap::is_global_config_account(&account.data) {
94        return pumpswap::parse_global_config(account, metadata);
95    }
96    if pumpswap::is_pool_account(&account.data) {
97        return pumpswap::parse_pool(account, metadata);
98    }
99    None
100}
101
102fn parse_pumpfun_account(account: &AccountData, metadata: EventMetadata) -> Option<DexEvent> {
103    use crate::core::events::{PumpFunGlobal, PumpFunGlobalAccountEvent};
104
105    const GLOBAL_DISCRIMINATOR: &[u8; 8] = &[167, 232, 232, 177, 200, 108, 114, 127];
106    if !has_discriminator(&account.data, GLOBAL_DISCRIMINATOR) {
107        return None;
108    }
109
110    let data = &account.data[8..];
111    let mut offset = 0usize;
112    let initialized = read_u8(data, offset)? != 0;
113    offset += 1;
114    let authority = read_pubkey(data, offset)?;
115    offset += 32;
116    let fee_recipient = read_pubkey(data, offset)?;
117    offset += 32;
118    let initial_virtual_token_reserves = read_u64_le(data, offset)?;
119    offset += 8;
120    let initial_virtual_sol_reserves = read_u64_le(data, offset)?;
121    offset += 8;
122    let initial_real_token_reserves = read_u64_le(data, offset)?;
123    offset += 8;
124    let token_total_supply = read_u64_le(data, offset)?;
125    offset += 8;
126    let fee_basis_points = read_u64_le(data, offset)?;
127    offset += 8;
128    let withdraw_authority = read_pubkey(data, offset)?;
129    offset += 32;
130    let enable_migrate = read_u8(data, offset)? != 0;
131    offset += 1;
132    let pool_migration_fee = read_u64_le(data, offset)?;
133    offset += 8;
134    let creator_fee_basis_points = read_u64_le(data, offset)?;
135    offset += 8;
136    let mut fee_recipients = [solana_sdk::pubkey::Pubkey::default(); 8];
137    for i in 0..8 {
138        fee_recipients[i] = read_pubkey(data, offset)?;
139        offset += 32;
140    }
141    let set_creator_authority = read_pubkey(data, offset)?;
142    offset += 32;
143    let admin_set_creator_authority = read_pubkey(data, offset)?;
144    offset += 32;
145    let create_v2_enabled = read_u8(data, offset)? != 0;
146    offset += 1;
147    let whitelist_pda = read_pubkey(data, offset)?;
148    offset += 32;
149    let reserved_fee_recipient = read_pubkey(data, offset)?;
150    offset += 32;
151    let mayhem_mode_enabled = read_u8(data, offset)? != 0;
152    offset += 1;
153    let mut reserved_fee_recipients = [solana_sdk::pubkey::Pubkey::default(); 7];
154    for i in 0..7 {
155        reserved_fee_recipients[i] = read_pubkey(data, offset)?;
156        offset += 32;
157    }
158    let _is_cashback_enabled = read_u8(data, offset)? != 0;
159    offset += 1;
160    let _buyback_fee_recipients = {
161        let mut keys = [solana_sdk::pubkey::Pubkey::default(); 8];
162        for i in 0..8 {
163            keys[i] = read_pubkey(data, offset)?;
164            offset += 32;
165        }
166        keys
167    };
168
169    let global = PumpFunGlobal {
170        initialized,
171        authority,
172        fee_recipient,
173        initial_virtual_token_reserves,
174        initial_virtual_sol_reserves,
175        initial_real_token_reserves,
176        token_total_supply,
177        fee_basis_points,
178        withdraw_authority,
179        enable_migrate,
180        pool_migration_fee,
181        creator_fee_basis_points,
182        fee_recipients,
183        set_creator_authority,
184        admin_set_creator_authority,
185        create_v2_enabled,
186        whitelist_pda,
187        reserved_fee_recipient,
188        mayhem_mode_enabled,
189        reserved_fee_recipients,
190    };
191
192    Some(DexEvent::PumpFunGlobalAccount(PumpFunGlobalAccountEvent {
193        metadata,
194        pubkey: account.pubkey,
195        global,
196    }))
197}