This commit is contained in:
2026-06-15 20:16:27 +02:00
parent 3b908b318e
commit 045af4931c
44 changed files with 5328 additions and 113 deletions

View File

@@ -62,6 +62,18 @@ impl TradeAggregationService {
if !crate::is_dex_trade_event_kind(decoded_event.event_kind.as_str()) {
continue;
}
if crate::trade_aggregation::should_skip_pump_fun_duplicate_trade_event(
decoded_event,
&decoded_events,
) {
tracing::debug!(
event_kind = %decoded_event.event_kind,
decoded_event_id = ?decoded_event.id,
transaction_signature = %transaction.signature,
"skipping duplicate pump_fun trade_event because an instruction trade exists"
);
continue;
}
let event_context =
crate::trade_aggregation_context::load_trade_aggregation_decoded_event_context(
self.database.as_ref(),
@@ -200,6 +212,68 @@ impl TradeAggregationService {
}
}
fn should_skip_pump_fun_duplicate_trade_event(
decoded_event: &crate::DexDecodedEventDto,
decoded_events: &[crate::DexDecodedEventDto],
) -> bool {
if decoded_event.event_kind.as_str() != "pump_fun.trade_event" {
return false;
}
let trade_instruction_id = pump_fun_payload_instruction_id(decoded_event.payload_json.as_str());
for sibling in decoded_events {
if sibling.id == decoded_event.id {
continue;
}
if !is_direct_materialized_pump_fun_instruction_trade_kind(sibling.event_kind.as_str()) {
continue;
}
let sibling_instruction_id = pump_fun_payload_instruction_id(sibling.payload_json.as_str());
if trade_instruction_id.is_some()
&& sibling_instruction_id.is_some()
&& trade_instruction_id != sibling_instruction_id
{
continue;
}
return true;
}
return false;
}
fn is_direct_materialized_pump_fun_instruction_trade_kind(event_kind: &str) -> bool {
match event_kind {
"pump_fun.buy" => return true,
"pump_fun.sell" => return true,
"pump_fun.buy_exact_sol_in" => return true,
_ => return false,
}
}
fn pump_fun_payload_instruction_id(payload_json: &str) -> std::option::Option<i64> {
let parsed_result = serde_json::from_str::<serde_json::Value>(payload_json);
let parsed = match parsed_result {
Ok(parsed) => parsed,
Err(_) => return None,
};
let object = match parsed.as_object() {
Some(object) => object,
None => return None,
};
let value = match object.get("instructionId") {
Some(value) => value,
None => return None,
};
if let Some(number) = value.as_i64() {
return Some(number);
}
if let Some(text) = value.as_str() {
let parsed_number = text.parse::<i64>();
match parsed_number {
Ok(parsed_number) => return Some(parsed_number),
Err(_) => return None,
}
}
return None;
}
fn transaction_has_effective_error(transaction: &crate::ChainTransactionDto) -> bool {
let err_json = match transaction.err_json.as_ref() {