solana_tx_decoding/instruction/pumpfun/
process_pumpfun_event_instruction.rs1use borsh::BorshDeserialize;
2use solana_central::Instruction;
3use solana_central::Pools;
4use solana_central::SwapDirection;
5use solana_central::SwapTx;
6use solana_central::constants::LAMPORTS_PER_SOL;
7use solana_central::constants::{PUMP_CONSTANTS, TOKENS};
8use solana_central::derive_bonding_curve;
9use solana_central::protocol_idls::pumpfun::PfTradeEventIdlCurrent;
10use solana_central::protocol_idls::pumpfun::PfTradeEventIdlOld;
11use solana_sdk::pubkey::Pubkey;
12use solana_sdk::signature::Signature;
13use std::collections::HashSet;
14
15pub fn process_pumpfun_event_instruction(
19 instruction: &Instruction,
20 block_time: u64,
21 slot: u64,
22 index: u64,
23 atomic_instruction_index: u8,
24 signers: &HashSet<Pubkey>,
25 signature: &Signature,
26) -> SwapTx {
27 let token_address;
28 let is_buy;
29 let fee_fraction_lp;
30 let sol_amount;
31 let total_fee;
32 let token_amount;
33 let pool_token_a_vault_amount;
34 let pool_token_b_vault_amount;
35 let virtual_sol_reserves;
36 let virtual_token_reserves;
37
38 if instruction.data.len() == 266
46 || instruction.data.len() == 273
47 || instruction.data.len() == 274
48 || instruction.data.len() == 286
49 {
50 let decoded_layout = PfTradeEventIdlCurrent::try_from_slice(&instruction.data[..266]).unwrap();
51 token_address = decoded_layout.mint;
52 is_buy = decoded_layout.is_buy;
53 sol_amount = decoded_layout.sol_amount;
54 total_fee = decoded_layout.creator_fee + decoded_layout.fee;
55 token_amount = decoded_layout.token_amount;
56 pool_token_a_vault_amount = decoded_layout.real_token_reserves;
57 pool_token_b_vault_amount = decoded_layout.real_sol_reserves;
58 virtual_sol_reserves = decoded_layout.virtual_sol_reserves;
59 virtual_token_reserves = decoded_layout.virtual_token_reserves;
60 fee_fraction_lp =
61 (decoded_layout.fee_basis_points + decoded_layout.creator_fee_basis_points) * 100000;
62 }
63 else if instruction.data.len() == 137 {
65 let decoded_layout = PfTradeEventIdlOld::try_from_slice(instruction.data).unwrap();
66 token_address = decoded_layout.mint;
67 is_buy = decoded_layout.is_buy;
68 sol_amount = decoded_layout.sol_amount;
69 token_amount = decoded_layout.token_amount;
70 pool_token_a_vault_amount =
71 decoded_layout.virtual_token_reserves - PUMP_CONSTANTS.bc_init_virtual_token_reserve_diff;
72 pool_token_b_vault_amount =
73 decoded_layout.virtual_sol_reserves - PUMP_CONSTANTS.bc_init_virtual_sol_reserves;
74 virtual_sol_reserves = decoded_layout.virtual_sol_reserves;
75 virtual_token_reserves = decoded_layout.virtual_token_reserves;
76 fee_fraction_lp = 10000000;
81 total_fee = sol_amount / 100;
83 } else {
84 panic!(
85 "Pumpfun: Found a swap event, but data length is not recognized, tx signature: {}",
86 signature
87 );
88 }
89
90 let market_address = derive_bonding_curve(&token_address);
91 let direction;
92 let swapped_amount_in;
93 let swapped_amount_received;
94
95 if is_buy {
96 direction = SwapDirection::BToA;
97 swapped_amount_in = sol_amount + total_fee;
98 swapped_amount_received = token_amount;
99 } else {
100 direction = SwapDirection::AToB;
101 swapped_amount_in = token_amount;
102 swapped_amount_received = sol_amount - total_fee;
103 }
104
105 SwapTx {
106 pool: Pools::PfBondingCurve,
107 direction,
108 block_time,
109 slot,
110 index,
111 atomic_instruction_index,
112 fee_fraction_lp,
113
114 swapped_amount_in,
116 swapped_amount_received,
118 pool_token_a_vault_amount,
120 pool_token_b_vault_amount,
121 price_a_b_lp: (virtual_token_reserves as u128 * LAMPORTS_PER_SOL
122 / virtual_sol_reserves as u128),
123 price_b_a_lp: (virtual_sol_reserves as u128 * LAMPORTS_PER_SOL
124 / virtual_token_reserves as u128),
125
126 token_a_address: token_address,
127 token_b_address: TOKENS.wsol,
128 market_address,
129 signature: signature.clone(),
130 signers: signers.clone(),
131 }
132}