mirror of
https://github.com/0xfnzero/solana-streamer.git
synced 2026-08-15 18:08:05 +00:00
refactor: restructure event handling from trait objects to enum pattern
- Convert UnifiedEvent from trait object (Box<dyn UnifiedEvent>) to concrete enum type - Remove match_event! macro in favor of native match expressions - Simplify event metadata access: event.event_type() -> event.metadata().event_type - Unify event callback signatures: Fn(Box<dyn UnifiedEvent>) -> Fn(UnifiedEvent) - Update all example code to use the new enum-based event system - Optimize type system to reduce runtime overhead and improve type safety Affected scope: - Core event parser and processor - All protocol event definitions (PumpFun, PumpSwap, Bonk, Raydium series, etc.) - gRPC and Shred streaming modules - All example code
This commit is contained in:
@@ -1,79 +1,6 @@
|
||||
pub mod types;
|
||||
pub mod utils;
|
||||
pub mod filter;
|
||||
pub mod high_performance_clock;
|
||||
|
||||
/// 自动生成UnifiedEvent trait实现的宏
|
||||
#[macro_export]
|
||||
macro_rules! impl_unified_event {
|
||||
// 带有自定义ID表达式的版本
|
||||
($struct_name:ident, $($field:ident),*) => {
|
||||
impl $crate::streaming::event_parser::core::traits::UnifiedEvent for $struct_name {
|
||||
fn event_type(&self) -> $crate::streaming::event_parser::common::types::EventType {
|
||||
self.metadata.event_type.clone()
|
||||
}
|
||||
|
||||
fn signature(&self) -> &solana_sdk::signature::Signature {
|
||||
&self.metadata.signature
|
||||
}
|
||||
|
||||
fn slot(&self) -> u64 {
|
||||
self.metadata.slot
|
||||
}
|
||||
|
||||
fn recv_us(&self) -> i64 {
|
||||
self.metadata.recv_us
|
||||
}
|
||||
|
||||
fn handle_us(&self) -> i64 {
|
||||
self.metadata.handle_us
|
||||
}
|
||||
|
||||
fn set_handle_us(&mut self, handle_us: i64) {
|
||||
self.metadata.handle_us = handle_us;
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn clone_boxed(&self) -> Box<dyn $crate::streaming::event_parser::core::traits::UnifiedEvent> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
|
||||
fn merge(&mut self, other: &dyn $crate::streaming::event_parser::core::traits::UnifiedEvent) {
|
||||
if let Some(_e) = other.as_any().downcast_ref::<$struct_name>() {
|
||||
$(
|
||||
self.$field = _e.$field.clone();
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
fn set_swap_data(&mut self, swap_data: $crate::streaming::event_parser::common::types::SwapData) {
|
||||
self.metadata.set_swap_data(swap_data);
|
||||
}
|
||||
|
||||
fn swap_data_is_parsed(&self) -> bool {
|
||||
self.metadata.swap_data.is_some()
|
||||
}
|
||||
|
||||
fn outer_index(&self) -> i64 {
|
||||
self.metadata.outer_index
|
||||
}
|
||||
|
||||
fn inner_index(&self) -> Option<i64> {
|
||||
self.metadata.inner_index
|
||||
}
|
||||
fn transaction_index(&self) -> Option<u64> {
|
||||
self.metadata.transaction_index
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub mod types;
|
||||
pub mod utils;
|
||||
pub use types::*;
|
||||
pub use utils::*;
|
||||
|
||||
@@ -4,23 +4,7 @@ use serde::{Deserialize, Serialize};
|
||||
use solana_sdk::{pubkey::Pubkey, signature::Signature};
|
||||
use std::{borrow::Cow, fmt, str::FromStr, sync::Arc};
|
||||
|
||||
use crate::{
|
||||
match_event,
|
||||
streaming::{
|
||||
common::SimdUtils,
|
||||
event_parser::{
|
||||
protocols::{
|
||||
bonk::BonkTradeEvent,
|
||||
pumpfun::PumpFunTradeEvent,
|
||||
pumpswap::{PumpSwapBuyEvent, PumpSwapSellEvent},
|
||||
raydium_amm_v4::RaydiumAmmV4SwapEvent,
|
||||
raydium_clmm::{RaydiumClmmSwapEvent, RaydiumClmmSwapV2Event},
|
||||
raydium_cpmm::RaydiumCpmmSwapEvent,
|
||||
},
|
||||
UnifiedEvent,
|
||||
},
|
||||
},
|
||||
};
|
||||
use crate::streaming::{common::SimdUtils, event_parser::UnifiedEvent};
|
||||
|
||||
// Object pool size configuration
|
||||
const EVENT_METADATA_POOL_SIZE: usize = 1000;
|
||||
@@ -364,7 +348,7 @@ lazy_static::lazy_static! {
|
||||
|
||||
/// Parse token transfer data from next instructions
|
||||
pub fn parse_swap_data_from_next_instructions(
|
||||
event: &dyn UnifiedEvent,
|
||||
event: &UnifiedEvent,
|
||||
inner_instruction: &solana_transaction_status::InnerInstructions,
|
||||
current_index: i8,
|
||||
accounts: &[Pubkey],
|
||||
@@ -378,7 +362,7 @@ pub fn parse_swap_data_from_next_instructions(
|
||||
};
|
||||
|
||||
// 先根据 event 取出关键信息
|
||||
let mut user: Option<Pubkey> = None;
|
||||
// let mut user: Option<Pubkey> = None;
|
||||
let mut from_mint: Option<Pubkey> = None;
|
||||
let mut to_mint: Option<Pubkey> = None;
|
||||
let mut user_from_token: Option<Pubkey> = None;
|
||||
@@ -386,63 +370,66 @@ pub fn parse_swap_data_from_next_instructions(
|
||||
let mut from_vault: Option<Pubkey> = None;
|
||||
let mut to_vault: Option<Pubkey> = None;
|
||||
|
||||
match_event!(&*event, {
|
||||
BonkTradeEvent => |e: BonkTradeEvent| {
|
||||
user = Some(e.payer);
|
||||
match event {
|
||||
UnifiedEvent::BonkTradeEvent(e) => {
|
||||
// user = Some(e.payer);
|
||||
from_mint = Some(e.base_token_mint);
|
||||
to_mint = Some(e.quote_token_mint);
|
||||
user_from_token = Some(e.user_base_token);
|
||||
user_to_token = Some(e.user_quote_token);
|
||||
from_vault = Some(e.base_vault);
|
||||
to_vault = Some(e.quote_vault);
|
||||
},
|
||||
PumpFunTradeEvent => |e: PumpFunTradeEvent| {
|
||||
}
|
||||
UnifiedEvent::PumpFunTradeEvent(e) => {
|
||||
swap_data.from_mint = if e.is_buy { *SOL_MINT } else { e.mint };
|
||||
swap_data.to_mint = if e.is_buy { e.mint } else { *SOL_MINT };
|
||||
},
|
||||
PumpSwapBuyEvent => |e: PumpSwapBuyEvent| {
|
||||
swap_data.to_mint = if e.is_buy { e.mint } else { *SOL_MINT };
|
||||
}
|
||||
UnifiedEvent::PumpSwapBuyEvent(e) => {
|
||||
swap_data.from_mint = e.quote_mint;
|
||||
swap_data.to_mint = e.base_mint;
|
||||
},
|
||||
PumpSwapSellEvent => |e: PumpSwapSellEvent| {
|
||||
swap_data.to_mint = e.base_mint;
|
||||
}
|
||||
UnifiedEvent::PumpSwapSellEvent(e) => {
|
||||
swap_data.from_mint = e.base_mint;
|
||||
swap_data.to_mint = e.quote_mint;
|
||||
},
|
||||
RaydiumCpmmSwapEvent => |e: RaydiumCpmmSwapEvent| {
|
||||
user = Some(e.payer);
|
||||
swap_data.to_mint = e.quote_mint;
|
||||
}
|
||||
UnifiedEvent::RaydiumCpmmSwapEvent(e) => {
|
||||
// user = Some(e.payer);
|
||||
from_mint = Some(e.input_token_mint);
|
||||
to_mint = Some(e.output_token_mint);
|
||||
to_mint = Some(e.output_token_mint);
|
||||
user_from_token = Some(e.input_token_account);
|
||||
user_to_token = Some(e.output_token_account);
|
||||
user_to_token = Some(e.output_token_account);
|
||||
from_vault = Some(e.input_vault);
|
||||
to_vault = Some(e.output_vault);
|
||||
},
|
||||
RaydiumClmmSwapEvent => |e: RaydiumClmmSwapEvent| {
|
||||
user = Some(e.payer);
|
||||
swap_data.description = Some("Unable to get from_mint and to_mint from RaydiumClmmSwapEvent".into());
|
||||
to_vault = Some(e.output_vault);
|
||||
}
|
||||
UnifiedEvent::RaydiumClmmSwapEvent(e) => {
|
||||
// user = Some(e.payer);
|
||||
swap_data.description =
|
||||
Some("Unable to get from_mint and to_mint from RaydiumClmmSwapEvent".into());
|
||||
user_from_token = Some(e.input_token_account);
|
||||
user_to_token = Some(e.output_token_account);
|
||||
user_to_token = Some(e.output_token_account);
|
||||
from_vault = Some(e.input_vault);
|
||||
to_vault = Some(e.output_vault);
|
||||
},
|
||||
RaydiumClmmSwapV2Event => |e: RaydiumClmmSwapV2Event| {
|
||||
user = Some(e.payer);
|
||||
to_vault = Some(e.output_vault);
|
||||
}
|
||||
UnifiedEvent::RaydiumClmmSwapV2Event(e) => {
|
||||
// user = Some(e.payer);
|
||||
from_mint = Some(e.input_vault_mint);
|
||||
to_mint = Some(e.output_vault_mint);
|
||||
to_mint = Some(e.output_vault_mint);
|
||||
user_from_token = Some(e.input_token_account);
|
||||
user_to_token = Some(e.output_token_account);
|
||||
user_to_token = Some(e.output_token_account);
|
||||
from_vault = Some(e.input_vault);
|
||||
to_vault = Some(e.output_vault);
|
||||
},
|
||||
RaydiumAmmV4SwapEvent => |e: RaydiumAmmV4SwapEvent| {
|
||||
user = Some(e.user_source_owner);
|
||||
swap_data.description = Some("Unable to get from_mint and to_mint from RaydiumAmmV4SwapEvent".into());
|
||||
to_vault = Some(e.output_vault);
|
||||
}
|
||||
UnifiedEvent::RaydiumAmmV4SwapEvent(e) => {
|
||||
// user = Some(e.user_source_owner);
|
||||
swap_data.description =
|
||||
Some("Unable to get from_mint and to_mint from RaydiumAmmV4SwapEvent".into());
|
||||
user_from_token = Some(e.user_source_token_account);
|
||||
user_to_token = Some(e.user_destination_token_account);
|
||||
user_to_token = Some(e.user_destination_token_account);
|
||||
from_vault = Some(e.pool_pc_token_account);
|
||||
to_vault = Some(e.pool_coin_token_account);
|
||||
},
|
||||
});
|
||||
to_vault = Some(e.pool_coin_token_account);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let user_to_token = user_to_token.unwrap_or_default();
|
||||
let user_from_token = user_from_token.unwrap_or_default();
|
||||
@@ -531,7 +518,7 @@ pub fn parse_swap_data_from_next_instructions(
|
||||
/// Parse token transfer data from next instructions
|
||||
/// TODO: - wait refactor
|
||||
pub fn parse_swap_data_from_next_grpc_instructions(
|
||||
event: &dyn UnifiedEvent,
|
||||
event: &UnifiedEvent,
|
||||
inner_instruction: &yellowstone_grpc_proto::prelude::InnerInstructions,
|
||||
current_index: i8,
|
||||
accounts: &[Pubkey],
|
||||
@@ -545,7 +532,7 @@ pub fn parse_swap_data_from_next_grpc_instructions(
|
||||
};
|
||||
|
||||
// 先根据 event 取出关键信息
|
||||
let mut user: Option<Pubkey> = None;
|
||||
// let mut user: Option<Pubkey> = None;
|
||||
let mut from_mint: Option<Pubkey> = None;
|
||||
let mut to_mint: Option<Pubkey> = None;
|
||||
let mut user_from_token: Option<Pubkey> = None;
|
||||
@@ -553,63 +540,66 @@ pub fn parse_swap_data_from_next_grpc_instructions(
|
||||
let mut from_vault: Option<Pubkey> = None;
|
||||
let mut to_vault: Option<Pubkey> = None;
|
||||
|
||||
match_event!(&*event, {
|
||||
BonkTradeEvent => |e: BonkTradeEvent| {
|
||||
user = Some(e.payer);
|
||||
match event {
|
||||
UnifiedEvent::BonkTradeEvent(e) => {
|
||||
// user = Some(e.payer);
|
||||
from_mint = Some(e.base_token_mint);
|
||||
to_mint = Some(e.quote_token_mint);
|
||||
user_from_token = Some(e.user_base_token);
|
||||
user_to_token = Some(e.user_quote_token);
|
||||
from_vault = Some(e.base_vault);
|
||||
to_vault = Some(e.quote_vault);
|
||||
},
|
||||
PumpFunTradeEvent => |e: PumpFunTradeEvent| {
|
||||
}
|
||||
UnifiedEvent::PumpFunTradeEvent(e) => {
|
||||
swap_data.from_mint = if e.is_buy { *SOL_MINT } else { e.mint };
|
||||
swap_data.to_mint = if e.is_buy { e.mint } else { *SOL_MINT };
|
||||
},
|
||||
PumpSwapBuyEvent => |e: PumpSwapBuyEvent| {
|
||||
swap_data.to_mint = if e.is_buy { e.mint } else { *SOL_MINT };
|
||||
}
|
||||
UnifiedEvent::PumpSwapBuyEvent(e) => {
|
||||
swap_data.from_mint = e.quote_mint;
|
||||
swap_data.to_mint = e.base_mint;
|
||||
},
|
||||
PumpSwapSellEvent => |e: PumpSwapSellEvent| {
|
||||
swap_data.to_mint = e.base_mint;
|
||||
}
|
||||
UnifiedEvent::PumpSwapSellEvent(e) => {
|
||||
swap_data.from_mint = e.base_mint;
|
||||
swap_data.to_mint = e.quote_mint;
|
||||
},
|
||||
RaydiumCpmmSwapEvent => |e: RaydiumCpmmSwapEvent| {
|
||||
user = Some(e.payer);
|
||||
swap_data.to_mint = e.quote_mint;
|
||||
}
|
||||
UnifiedEvent::RaydiumCpmmSwapEvent(e) => {
|
||||
// user = Some(e.payer);
|
||||
from_mint = Some(e.input_token_mint);
|
||||
to_mint = Some(e.output_token_mint);
|
||||
to_mint = Some(e.output_token_mint);
|
||||
user_from_token = Some(e.input_token_account);
|
||||
user_to_token = Some(e.output_token_account);
|
||||
user_to_token = Some(e.output_token_account);
|
||||
from_vault = Some(e.input_vault);
|
||||
to_vault = Some(e.output_vault);
|
||||
},
|
||||
RaydiumClmmSwapEvent => |e: RaydiumClmmSwapEvent| {
|
||||
user = Some(e.payer);
|
||||
swap_data.description = Some("Unable to get from_mint and to_mint from RaydiumClmmSwapEvent".into());
|
||||
to_vault = Some(e.output_vault);
|
||||
}
|
||||
UnifiedEvent::RaydiumClmmSwapEvent(e) => {
|
||||
// user = Some(e.payer);
|
||||
swap_data.description =
|
||||
Some("Unable to get from_mint and to_mint from RaydiumClmmSwapEvent".into());
|
||||
user_from_token = Some(e.input_token_account);
|
||||
user_to_token = Some(e.output_token_account);
|
||||
user_to_token = Some(e.output_token_account);
|
||||
from_vault = Some(e.input_vault);
|
||||
to_vault = Some(e.output_vault);
|
||||
},
|
||||
RaydiumClmmSwapV2Event => |e: RaydiumClmmSwapV2Event| {
|
||||
user = Some(e.payer);
|
||||
to_vault = Some(e.output_vault);
|
||||
}
|
||||
UnifiedEvent::RaydiumClmmSwapV2Event(e) => {
|
||||
// user = Some(e.payer);
|
||||
from_mint = Some(e.input_vault_mint);
|
||||
to_mint = Some(e.output_vault_mint);
|
||||
to_mint = Some(e.output_vault_mint);
|
||||
user_from_token = Some(e.input_token_account);
|
||||
user_to_token = Some(e.output_token_account);
|
||||
user_to_token = Some(e.output_token_account);
|
||||
from_vault = Some(e.input_vault);
|
||||
to_vault = Some(e.output_vault);
|
||||
},
|
||||
RaydiumAmmV4SwapEvent => |e: RaydiumAmmV4SwapEvent| {
|
||||
user = Some(e.user_source_owner);
|
||||
swap_data.description = Some("Unable to get from_mint and to_mint from RaydiumAmmV4SwapEvent".into());
|
||||
to_vault = Some(e.output_vault);
|
||||
}
|
||||
UnifiedEvent::RaydiumAmmV4SwapEvent(e) => {
|
||||
// user = Some(e.user_source_owner);
|
||||
swap_data.description =
|
||||
Some("Unable to get from_mint and to_mint from RaydiumAmmV4SwapEvent".into());
|
||||
user_from_token = Some(e.user_source_token_account);
|
||||
user_to_token = Some(e.user_destination_token_account);
|
||||
user_to_token = Some(e.user_destination_token_account);
|
||||
from_vault = Some(e.pool_pc_token_account);
|
||||
to_vault = Some(e.pool_coin_token_account);
|
||||
},
|
||||
});
|
||||
to_vault = Some(e.pool_coin_token_account);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let user_to_token = user_to_token.unwrap_or_default();
|
||||
let user_from_token = user_from_token.unwrap_or_default();
|
||||
|
||||
Reference in New Issue
Block a user