feat: support Pump.fun V2 (Mayhem Mode) and update protocol structures for Nov 11 breaking changes

This commit is contained in:
ysq
2025-11-09 23:30:48 +08:00
parent 3a9fed4a9c
commit 9e4f71dbb2
10 changed files with 154 additions and 16 deletions
@@ -1,9 +1,9 @@
use crate::streaming::event_parser::{
common::{EventMetadata, EventType},
protocols::pumpfun::{
discriminators, pumpfun_create_token_event_log_decode, pumpfun_migrate_event_log_decode,
pumpfun_trade_event_log_decode, PumpFunCreateTokenEvent, PumpFunMigrateEvent,
PumpFunTradeEvent,
discriminators, pumpfun_create_token_event_log_decode, pumpfun_create_v2_token_event_log_decode,
pumpfun_migrate_event_log_decode, pumpfun_trade_event_log_decode, PumpFunCreateTokenEvent,
PumpFunCreateV2TokenEvent, PumpFunMigrateEvent, PumpFunTradeEvent,
},
DexEvent,
};
@@ -26,6 +26,9 @@ pub fn parse_pumpfun_instruction_data(
discriminators::CREATE_TOKEN_IX => {
parse_create_token_instruction(data, accounts, metadata)
}
discriminators::CREATE_V2_TOKEN_IX => {
parse_create_v2_token_instruction(data, accounts, metadata)
}
discriminators::BUY_IX => {
parse_buy_instruction(data, accounts, metadata)
}
@@ -179,6 +182,69 @@ fn parse_create_token_instruction(
}))
}
/// 解析创建 V2 代币指令事件 (SPL-22 Token, Mayhem Mode)
fn parse_create_v2_token_instruction(
data: &[u8],
accounts: &[Pubkey],
mut metadata: EventMetadata,
) -> Option<DexEvent> {
metadata.event_type = EventType::PumpFunCreateV2Token;
if data.len() < 16 || accounts.len() < 11 {
return None;
}
let mut offset = 0;
if offset + 4 > data.len() {
return None;
}
let name_len = u32::from_le_bytes(data[offset..offset + 4].try_into().unwrap()) as usize;
offset += 4;
if offset + name_len > data.len() {
return None;
}
let name = String::from_utf8_lossy(&data[offset..offset + name_len]);
offset += name_len;
if offset + 4 > data.len() {
return None;
}
let symbol_len = u32::from_le_bytes(data[offset..offset + 4].try_into().unwrap()) as usize;
offset += 4;
if offset + symbol_len > data.len() {
return None;
}
let symbol = String::from_utf8_lossy(&data[offset..offset + symbol_len]);
offset += symbol_len;
if offset + 4 > data.len() {
return None;
}
let uri_len = u32::from_le_bytes(data[offset..offset + 4].try_into().unwrap()) as usize;
offset += 4;
if offset + uri_len > data.len() {
return None;
}
let uri = String::from_utf8_lossy(&data[offset..offset + uri_len]);
offset += uri_len;
let creator = if offset + 32 <= data.len() {
Pubkey::new_from_array(data[offset..offset + 32].try_into().ok()?)
} else {
Pubkey::default()
};
Some(DexEvent::PumpFunCreateV2TokenEvent(PumpFunCreateV2TokenEvent {
metadata,
name: name.to_string(),
symbol: symbol.to_string(),
uri: uri.to_string(),
creator,
mint: accounts[0],
mint_authority: accounts[1],
bonding_curve: accounts[2],
associated_bonding_curve: accounts[3],
user: accounts[7],
..Default::default()
}))
}
// 解析买入指令事件
fn parse_buy_instruction(
data: &[u8],
@@ -187,7 +253,7 @@ fn parse_buy_instruction(
) -> Option<DexEvent> {
metadata.event_type = EventType::PumpFunBuy;
if data.len() < 16 || accounts.len() < 13 {
if data.len() < 16 || accounts.len() < 16 {
return None;
}
let amount = u64::from_le_bytes(data[0..8].try_into().unwrap());
@@ -208,6 +274,8 @@ fn parse_buy_instruction(
program: accounts[11],
global_volume_accumulator: accounts[12],
user_volume_accumulator: accounts[13],
fee_config: accounts[14],
fee_program: accounts[15],
max_sol_cost,
amount,
is_buy: true,
@@ -223,7 +291,7 @@ fn parse_sell_instruction(
) -> Option<DexEvent> {
metadata.event_type = EventType::PumpFunSell;
if data.len() < 16 || accounts.len() < 11 {
if data.len() < 16 || accounts.len() < 14 {
return None;
}
let amount = u64::from_le_bytes(data[0..8].try_into().unwrap());
@@ -242,8 +310,10 @@ fn parse_sell_instruction(
token_program: accounts[9],
event_authority: accounts[10],
program: accounts[11],
global_volume_accumulator: *accounts.get(12).unwrap_or(&Pubkey::default()),
user_volume_accumulator: *accounts.get(13).unwrap_or(&Pubkey::default()),
global_volume_accumulator: Pubkey::default(),
user_volume_accumulator: Pubkey::default(),
fee_config: accounts[12],
fee_program: accounts[13],
min_sol_output,
amount,
is_buy: false,