refactor: optimize EventParser with idiomatic Rust patterns

This commit is contained in:
ysq
2025-10-12 23:01:13 +08:00
parent f85581ec61
commit d5fc686664
+120 -168
View File
@@ -224,7 +224,8 @@ impl EventParser {
let adapter_callback = Arc::new(move |event: &DexEvent| { let adapter_callback = Arc::new(move |event: &DexEvent| {
callback(event.clone()); callback(event.clone());
}); });
Self::parse_versioned_transaction( let accounts = versioned_tx.message.static_account_keys();
Self::parse_instruction_events_from_versioned_transaction(
protocols, protocols,
event_type_filter, event_type_filter,
&versioned_tx, &versioned_tx,
@@ -232,45 +233,13 @@ impl EventParser {
slot, slot,
block_time, block_time,
recv_us, recv_us,
accounts,
inner_instructions,
bot_wallet, bot_wallet,
transaction_index, transaction_index,
inner_instructions,
adapter_callback, adapter_callback,
) )
.await?; .await
Ok(())
}
async fn parse_versioned_transaction(
protocols: &[Protocol],
event_type_filter: Option<&EventTypeFilter>,
versioned_tx: &VersionedTransaction,
signature: Signature,
slot: Option<u64>,
block_time: Option<Timestamp>,
recv_us: i64,
bot_wallet: Option<Pubkey>,
transaction_index: Option<u64>,
inner_instructions: &[InnerInstructions],
callback: Arc<dyn for<'a> Fn(&'a DexEvent) + Send + Sync>,
) -> anyhow::Result<()> {
let accounts: Vec<Pubkey> = versioned_tx.message.static_account_keys().to_vec();
Self::parse_instruction_events_from_versioned_transaction(
protocols,
event_type_filter,
versioned_tx,
signature,
slot,
block_time,
recv_us,
&accounts,
inner_instructions,
bot_wallet,
transaction_index,
callback,
)
.await?;
Ok(())
} }
pub async fn parse_grpc_transaction_owned( pub async fn parse_grpc_transaction_owned(
@@ -351,9 +320,6 @@ impl EventParser {
} }
}) })
.collect(); .collect();
// 使用 Arc 包装共享数据,避免不必要的克隆
let accounts_arc = Arc::new(accounts);
let inner_instructions_arc = Arc::new(inner_instructions);
// 解析指令事件 // 解析指令事件
let instructions = &message.instructions; let instructions = &message.instructions;
Self::parse_instruction_events_from_grpc_transaction( Self::parse_instruction_events_from_grpc_transaction(
@@ -364,8 +330,8 @@ impl EventParser {
slot, slot,
block_time, block_time,
recv_us, recv_us,
&accounts_arc, &accounts,
&inner_instructions_arc, &inner_instructions,
bot_wallet, bot_wallet,
transaction_index, transaction_index,
callback.clone(), callback.clone(),
@@ -462,9 +428,6 @@ impl EventParser {
); );
accounts.extend_from_slice(versioned_tx.message.static_account_keys()); accounts.extend_from_slice(versioned_tx.message.static_account_keys());
accounts.extend(address_table_lookups); accounts.extend(address_table_lookups);
// 使用 Arc 包装共享数据,避免不必要的克隆
let accounts_arc = Arc::new(accounts);
let inner_instructions_arc = Arc::new(inner_instructions);
let slot = transaction.slot; let slot = transaction.slot;
let block_time = transaction.block_time.map(|t| Timestamp { seconds: t as i64, nanos: 0 }); let block_time = transaction.block_time.map(|t| Timestamp { seconds: t as i64, nanos: 0 });
@@ -480,15 +443,42 @@ impl EventParser {
Some(slot), Some(slot),
block_time, block_time,
recv_us, recv_us,
&accounts_arc, &accounts,
&inner_instructions_arc, inner_instructions,
bot_wallet, bot_wallet,
transaction_index, transaction_index,
callback.clone(), callback.clone(),
) )
.await?; .await
}
Ok(()) /// Helper function to create EventMetadata from common parameters
#[inline]
fn create_metadata(
config: &GenericEventParseConfig,
signature: Signature,
slot: u64,
block_time: Option<Timestamp>,
recv_us: i64,
outer_index: i64,
inner_index: Option<i64>,
transaction_index: Option<u64>,
) -> EventMetadata {
let timestamp = block_time.unwrap_or(Timestamp { seconds: 0, nanos: 0 });
let block_time_ms = timestamp.seconds * 1000 + (timestamp.nanos as i64) / 1_000_000;
EventMetadata::new(
signature,
slot,
timestamp.seconds,
block_time_ms,
config.protocol_type.clone(),
config.event_type.clone(),
config.program_id,
outer_index,
inner_index,
recv_us,
transaction_index,
)
} }
/// 通用的内联指令解析方法 /// 通用的内联指令解析方法
@@ -504,26 +494,19 @@ impl EventParser {
inner_index: Option<i64>, inner_index: Option<i64>,
transaction_index: Option<u64>, transaction_index: Option<u64>,
) -> Option<DexEvent> { ) -> Option<DexEvent> {
if let Some(parser) = config.inner_instruction_parser { config.inner_instruction_parser.and_then(|parser| {
let timestamp = block_time.unwrap_or(Timestamp { seconds: 0, nanos: 0 }); let metadata = Self::create_metadata(
let block_time_ms = timestamp.seconds * 1000 + (timestamp.nanos as i64) / 1_000_000; config,
let metadata = EventMetadata::new(
signature, signature,
slot, slot,
timestamp.seconds, block_time,
block_time_ms, recv_us,
config.protocol_type.clone(),
config.event_type.clone(),
config.program_id,
outer_index, outer_index,
inner_index, inner_index,
recv_us,
transaction_index, transaction_index,
); );
parser(data, metadata) parser(data, metadata)
} else { })
None
}
} }
/// 通用的指令解析方法 /// 通用的指令解析方法
@@ -540,26 +523,59 @@ impl EventParser {
inner_index: Option<i64>, inner_index: Option<i64>,
transaction_index: Option<u64>, transaction_index: Option<u64>,
) -> Option<DexEvent> { ) -> Option<DexEvent> {
if let Some(parser) = config.instruction_parser { config.instruction_parser.and_then(|parser| {
let timestamp = block_time.unwrap_or(Timestamp { seconds: 0, nanos: 0 }); let metadata = Self::create_metadata(
let block_time_ms = timestamp.seconds * 1000 + (timestamp.nanos as i64) / 1_000_000; config,
let metadata = EventMetadata::new(
signature, signature,
slot, slot,
timestamp.seconds, block_time,
block_time_ms, recv_us,
config.protocol_type.clone(),
config.event_type.clone(),
config.program_id,
outer_index, outer_index,
inner_index, inner_index,
recv_us,
transaction_index, transaction_index,
); );
parser(data, account_pubkeys, metadata) parser(data, account_pubkeys, metadata)
} else { })
None }
/// 从内联指令中解析事件数据 - 通用实现
#[allow(clippy::too_many_arguments)]
fn parse_events_from_inner_instruction_data(
data: &[u8],
signature: Signature,
slot: u64,
block_time: Option<Timestamp>,
recv_us: i64,
outer_index: i64,
inner_index: Option<i64>,
transaction_index: Option<u64>,
config: &GenericEventParseConfig,
) -> Vec<DexEvent> {
// Use SIMD-optimized data validation with correct discriminator length
let discriminator_len = config.inner_instruction_discriminator.len();
if !SimdUtils::validate_instruction_data_simd(data, 16, discriminator_len) {
return Vec::new();
} }
// Use SIMD-optimized discriminator matching
if !SimdUtils::fast_discriminator_match(data, config.inner_instruction_discriminator) {
return Vec::new();
}
let data = &data[16..];
Self::parse_inner_instruction_event(
config,
data,
signature,
slot,
block_time,
recv_us,
outer_index,
inner_index,
transaction_index,
)
.into_iter()
.collect()
} }
/// 从内联指令中解析事件数据 /// 从内联指令中解析事件数据
@@ -575,29 +591,8 @@ impl EventParser {
transaction_index: Option<u64>, transaction_index: Option<u64>,
config: &GenericEventParseConfig, config: &GenericEventParseConfig,
) -> Vec<DexEvent> { ) -> Vec<DexEvent> {
// Use SIMD-optimized data validation with correct discriminator length Self::parse_events_from_inner_instruction_data(
let discriminator_len = config.inner_instruction_discriminator.len();
if !SimdUtils::validate_instruction_data_simd(
&inner_instruction.data, &inner_instruction.data,
16,
discriminator_len,
) {
return Vec::new();
}
// Use SIMD-optimized discriminator matching
if !SimdUtils::fast_discriminator_match(
&inner_instruction.data,
config.inner_instruction_discriminator,
) {
return Vec::new();
}
let data = &inner_instruction.data[16..];
let mut events = Vec::new();
if let Some(event) = Self::parse_inner_instruction_event(
config,
data,
signature, signature,
slot, slot,
block_time, block_time,
@@ -605,10 +600,8 @@ impl EventParser {
outer_index, outer_index,
inner_index, inner_index,
transaction_index, transaction_index,
) { config,
events.push(event); )
}
events
} }
/// 从内联指令中解析事件数据 /// 从内联指令中解析事件数据
@@ -624,29 +617,8 @@ impl EventParser {
transaction_index: Option<u64>, transaction_index: Option<u64>,
config: &GenericEventParseConfig, config: &GenericEventParseConfig,
) -> Vec<DexEvent> { ) -> Vec<DexEvent> {
// Use SIMD-optimized data validation with correct discriminator length Self::parse_events_from_inner_instruction_data(
let discriminator_len = config.inner_instruction_discriminator.len();
if !SimdUtils::validate_instruction_data_simd(
&inner_instruction.data, &inner_instruction.data,
16,
discriminator_len,
) {
return Vec::new();
}
// Use SIMD-optimized discriminator matching
if !SimdUtils::fast_discriminator_match(
&inner_instruction.data,
config.inner_instruction_discriminator,
) {
return Vec::new();
}
let data = &inner_instruction.data[16..];
let mut events = Vec::new();
if let Some(event) = Self::parse_inner_instruction_event(
config,
data,
signature, signature,
slot, slot,
block_time, block_time,
@@ -654,10 +626,8 @@ impl EventParser {
outer_index, outer_index,
inner_index, inner_index,
transaction_index, transaction_index,
) { config,
events.push(event); )
}
events
} }
/// 从指令中解析事件 /// 从指令中解析事件
@@ -736,9 +706,7 @@ impl EventParser {
for (_disc, config, mut event) in all_results { for (_disc, config, mut event) in all_results {
// 阻塞处理:原有的同步逻辑 // 阻塞处理:原有的同步逻辑
let mut inner_instruction_event: Option<DexEvent> = None; let mut inner_instruction_event: Option<DexEvent> = None;
if inner_instructions.is_some() { if let Some(inner_instructions_ref) = inner_instructions {
let inner_instructions_ref = inner_instructions.unwrap();
// 并行执行两个任务 // 并行执行两个任务
let (inner_event_result, swap_data_result) = std::thread::scope(|s| { let (inner_event_result, swap_data_result) = std::thread::scope(|s| {
let inner_event_handle = s.spawn(|| { let inner_event_handle = s.spawn(|| {
@@ -762,7 +730,7 @@ impl EventParser {
}); });
let swap_data_handle = s.spawn(|| { let swap_data_handle = s.spawn(|| {
if !event.metadata().swap_data.is_some() { if event.metadata().swap_data.is_none() {
parse_swap_data_from_next_instructions( parse_swap_data_from_next_instructions(
&event, &event,
inner_instructions_ref, inner_instructions_ref,
@@ -878,9 +846,7 @@ impl EventParser {
for (_disc, config, mut event) in all_results { for (_disc, config, mut event) in all_results {
// 阻塞处理:原有的同步逻辑 // 阻塞处理:原有的同步逻辑
let mut inner_instruction_event: Option<DexEvent> = None; let mut inner_instruction_event: Option<DexEvent> = None;
if inner_instructions.is_some() { if let Some(inner_instructions_ref) = inner_instructions {
let inner_instructions_ref = inner_instructions.unwrap();
// 并行执行两个任务 // 并行执行两个任务
let (inner_event_result, swap_data_result) = std::thread::scope(|s| { let (inner_event_result, swap_data_result) = std::thread::scope(|s| {
let inner_event_handle = s.spawn(|| { let inner_event_handle = s.spawn(|| {
@@ -904,7 +870,7 @@ impl EventParser {
}); });
let swap_data_handle = s.spawn(|| { let swap_data_handle = s.spawn(|| {
if !event.metadata().swap_data.is_some() { if event.metadata().swap_data.is_none() {
parse_swap_data_from_next_grpc_instructions( parse_swap_data_from_next_grpc_instructions(
&event, &event,
inner_instructions_ref, inner_instructions_ref,
@@ -963,24 +929,18 @@ impl EventParser {
DexEvent::PumpFunCreateTokenEvent(token_info) DexEvent::PumpFunCreateTokenEvent(token_info)
} }
DexEvent::PumpFunTradeEvent(mut trade_info) => { DexEvent::PumpFunTradeEvent(mut trade_info) => {
if is_dev_address_in_signature(&signature, &trade_info.user) trade_info.is_dev_create_token_trade =
|| is_dev_address_in_signature(&signature, &trade_info.creator) is_dev_address_in_signature(&signature, &trade_info.user)
{ || is_dev_address_in_signature(&signature, &trade_info.creator);
trade_info.is_dev_create_token_trade = true; trade_info.is_bot = Some(trade_info.user) == bot_wallet;
} else if Some(trade_info.user) == bot_wallet {
trade_info.is_bot = true; if let Some(swap_data) = trade_info.metadata.swap_data.as_mut() {
} else { swap_data.from_amount = if trade_info.is_buy {
trade_info.is_dev_create_token_trade = false; trade_info.sol_amount
} } else {
if trade_info.metadata.swap_data.is_some() { trade_info.token_amount
trade_info.metadata.swap_data.as_mut().unwrap().from_amount = };
if trade_info.is_buy { swap_data.to_amount = if trade_info.is_buy {
trade_info.sol_amount
} else {
trade_info.token_amount
};
trade_info.metadata.swap_data.as_mut().unwrap().to_amount = if trade_info.is_buy
{
trade_info.token_amount trade_info.token_amount
} else { } else {
trade_info.sol_amount trade_info.sol_amount
@@ -989,20 +949,16 @@ impl EventParser {
DexEvent::PumpFunTradeEvent(trade_info) DexEvent::PumpFunTradeEvent(trade_info)
} }
DexEvent::PumpSwapBuyEvent(mut trade_info) => { DexEvent::PumpSwapBuyEvent(mut trade_info) => {
if trade_info.metadata.swap_data.is_some() { if let Some(swap_data) = trade_info.metadata.swap_data.as_mut() {
trade_info.metadata.swap_data.as_mut().unwrap().from_amount = swap_data.from_amount = trade_info.user_quote_amount_in;
trade_info.user_quote_amount_in; swap_data.to_amount = trade_info.base_amount_out;
trade_info.metadata.swap_data.as_mut().unwrap().to_amount =
trade_info.base_amount_out;
} }
DexEvent::PumpSwapBuyEvent(trade_info) DexEvent::PumpSwapBuyEvent(trade_info)
} }
DexEvent::PumpSwapSellEvent(mut trade_info) => { DexEvent::PumpSwapSellEvent(mut trade_info) => {
if trade_info.metadata.swap_data.is_some() { if let Some(swap_data) = trade_info.metadata.swap_data.as_mut() {
trade_info.metadata.swap_data.as_mut().unwrap().from_amount = swap_data.from_amount = trade_info.base_amount_in;
trade_info.base_amount_in; swap_data.to_amount = trade_info.user_quote_amount_out;
trade_info.metadata.swap_data.as_mut().unwrap().to_amount =
trade_info.user_quote_amount_out;
} }
DexEvent::PumpSwapSellEvent(trade_info) DexEvent::PumpSwapSellEvent(trade_info)
} }
@@ -1011,13 +967,9 @@ impl EventParser {
DexEvent::BonkPoolCreateEvent(pool_info) DexEvent::BonkPoolCreateEvent(pool_info)
} }
DexEvent::BonkTradeEvent(mut trade_info) => { DexEvent::BonkTradeEvent(mut trade_info) => {
if is_bonk_dev_address_in_signature(&signature, &trade_info.payer) { trade_info.is_dev_create_token_trade =
trade_info.is_dev_create_token_trade = true; is_bonk_dev_address_in_signature(&signature, &trade_info.payer);
} else if Some(trade_info.payer) == bot_wallet { trade_info.is_bot = Some(trade_info.payer) == bot_wallet;
trade_info.is_bot = true;
} else {
trade_info.is_dev_create_token_trade = false;
}
DexEvent::BonkTradeEvent(trade_info) DexEvent::BonkTradeEvent(trade_info)
} }
_ => event, _ => event,