From 20a1048020e6b38dbc6e250bcbb877b970fa13cd Mon Sep 17 00:00:00 2001 From: Wood Date: Sun, 8 Mar 2026 11:08:46 +0800 Subject: [PATCH] feat(pumpfun): parse 17th instruction account (account field) - Add PumpFunTradeEvent.account: Option for the 17th instruction account (index 16), labeled as 'Account' on block explorers. - Fill account in parse_buy_instruction, parse_buy_exact_sol_in_instruction, and parse_sell_instruction when accounts.get(16) is present. - Merge account from CPI log event into instruction event when merging. Made-with: Cursor --- .../event_parser/core/merger_event.rs | 3 ++ .../event_parser/protocols/pumpfun/events.rs | 3 ++ .../event_parser/protocols/pumpfun/parser.rs | 31 ++++++++----------- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/src/streaming/event_parser/core/merger_event.rs b/src/streaming/event_parser/core/merger_event.rs index ce4258b..11fc664 100644 --- a/src/streaming/event_parser/core/merger_event.rs +++ b/src/streaming/event_parser/core/merger_event.rs @@ -31,6 +31,9 @@ pub fn merge(instruction_event: &mut DexEvent, cpi_log_event: DexEvent) { e.cashback_fee_basis_points = cpie.cashback_fee_basis_points; e.cashback = cpie.cashback; e.is_cashback_coin = cpie.is_cashback_coin; + if cpie.account.is_some() { + e.account = cpie.account; + } } _ => {} }, diff --git a/src/streaming/event_parser/protocols/pumpfun/events.rs b/src/streaming/event_parser/protocols/pumpfun/events.rs index f09838d..b8ca923 100755 --- a/src/streaming/event_parser/protocols/pumpfun/events.rs +++ b/src/streaming/event_parser/protocols/pumpfun/events.rs @@ -295,6 +295,9 @@ pub struct PumpFunTradeEvent { pub fee_config: Pubkey, #[borsh(skip)] pub fee_program: Pubkey, + /// 17th instruction account (index 16), shown as "Account" on block explorers; present on some buy/sell. + #[borsh(skip)] + pub account: Option, // === IDL TradeEvent extension fields (aligned with sol-parser-sdk / pumpfun IDL) === #[borsh(skip)] diff --git a/src/streaming/event_parser/protocols/pumpfun/parser.rs b/src/streaming/event_parser/protocols/pumpfun/parser.rs index 7968fe8..127359e 100755 --- a/src/streaming/event_parser/protocols/pumpfun/parser.rs +++ b/src/streaming/event_parser/protocols/pumpfun/parser.rs @@ -268,12 +268,12 @@ fn parse_create_v2_token_instruction( })) } -/// 解析买入指令事件 -/// Buy 指令共 16 个固定账户(与 idl/pumpfun.json 一致): +/// Parse buy instruction event. +/// Buy has 16 fixed accounts + optional 17th (index 16, "Account" on block explorers): /// 0: global, 1: fee_recipient, 2: mint, 3: bonding_curve, 4: associated_bonding_curve, /// 5: associated_user, 6: user, 7: system_program, 8: token_program, 9: creator_vault, /// 10: event_authority, 11: program, 12: global_volume_accumulator, 13: user_volume_accumulator, -/// 14: fee_config, 15: fee_program. +/// 14: fee_config, 15: fee_program, 16 (optional): account. fn parse_buy_instruction( data: &[u8], accounts: &[Pubkey], @@ -304,6 +304,7 @@ fn parse_buy_instruction( user_volume_accumulator: accounts[13], fee_config: accounts[14], fee_program: accounts[15], + account: accounts.get(16).copied(), max_sol_cost, amount, is_buy: true, @@ -311,12 +312,9 @@ fn parse_buy_instruction( })) } -/// 解析 buy_exact_sol_in 指令事件 -/// 账户布局与 buy 相同,共 16 个固定账户: 0: global, 1: fee_recipient, 2: mint, 3: bonding_curve, -/// 4: associated_bonding_curve, 5: associated_user, 6: user, 7: system_program, 8: token_program, -/// 9: creator_vault, 10: event_authority, 11: program, 12: global_volume_accumulator, -/// 13: user_volume_accumulator, 14: fee_config, 15: fee_program. -/// 参数顺序与 buy 不同: spendable_sol_in (SOL), min_tokens_out (token). +/// Parse buy_exact_sol_in instruction event. +/// Same account layout as buy: 16 fixed + optional 17th (index 16). +/// Args: spendable_sol_in (SOL), min_tokens_out (token). fn parse_buy_exact_sol_in_instruction( data: &[u8], accounts: &[Pubkey], mut metadata: EventMetadata, @@ -327,7 +325,6 @@ fn parse_buy_exact_sol_in_instruction( return None; } - // 注意:buy_exact_sol_in 的参数顺序是先 SOL 再 token let spendable_sol_in = u64::from_le_bytes(data[0..8].try_into().unwrap()); let min_tokens_out = u64::from_le_bytes(data[8..16].try_into().unwrap()); @@ -349,19 +346,16 @@ fn parse_buy_exact_sol_in_instruction( user_volume_accumulator: accounts[13], fee_config: accounts[14], fee_program: accounts[15], - max_sol_cost: spendable_sol_in, // Map spendable_sol_in to max_sol_cost - amount: min_tokens_out, // Map min_tokens_out to amount + account: accounts.get(16).copied(), + max_sol_cost: spendable_sol_in, + amount: min_tokens_out, is_buy: true, ..Default::default() })) } -/// 解析卖出指令事件 -/// Sell 指令共 14 个固定账户(与 idl/pumpfun.json 一致): -/// 0: global, 1: fee_recipient, 2: mint, 3: bonding_curve, 4: associated_bonding_curve, -/// 5: associated_user, 6: user, 7: system_program, 8: creator_vault, 9: token_program, -/// 10: event_authority, 11: program, 12: fee_config, 13: fee_program. -/// remaining_accounts 可能含 user_volume_accumulator(返现)等。 +/// Parse sell instruction event. +/// Sell has 14 fixed accounts; some versions pass 17 accounts, index 16 = "Account" on block explorers. fn parse_sell_instruction( data: &[u8], accounts: &[Pubkey], @@ -392,6 +386,7 @@ fn parse_sell_instruction( user_volume_accumulator: Pubkey::default(), fee_config: accounts[12], fee_program: accounts[13], + account: accounts.get(16).copied(), min_sol_output, amount, is_buy: false,