solana_tx_decoding/instruction/pumpswap/
process_pumpswap_swap_instruction.rs1use solana_central::protocol_idls::pumpswap::{
2 PumpswapBuyEventIdl, PumpswapSellEventIdl,
3};
4use borsh::BorshDeserialize;
5use solana_central::constants::LAMPORTS_PER_SOL;
6use solana_central::Instruction;
7use solana_central::Pools;
8use solana_central::SwapDirection;
9use solana_central::SwapTx;
10use solana_sdk::pubkey::Pubkey;
11use solana_sdk::signature::Signature;
12use std::collections::HashSet;
13
14pub fn process_pumpswap_swap_instruction(
18 instruction: &Instruction,
19 swap_event_instruction: &Instruction,
20 direction: SwapDirection,
21 block_time: u64,
22 slot: u64,
23 index: u64,
24 atomic_instruction_index: u8,
25 signers: &HashSet<Pubkey>,
26 signature: &Signature,
27) -> SwapTx {
28 let token_a_address = instruction.tx_account_keys[instruction.accounts[3] as usize];
29 let token_b_address = instruction.tx_account_keys[instruction.accounts[4] as usize];
30 let market_address = instruction.tx_account_keys[instruction.accounts[0] as usize];
31
32 let swapped_amount_in;
33 let swapped_amount_received;
34 let pool_token_a_vault_amount;
35 let pool_token_b_vault_amount;
36 let fee_fraction_lp;
37
38 let event_len = swap_event_instruction.data.len();
39
40 if direction == SwapDirection::AToB {
42 let decoded_event = PumpswapSellEventIdl::try_from_slice(&swap_event_instruction.data).unwrap();
43
44 swapped_amount_in = decoded_event.base_amount_in;
45 swapped_amount_received = decoded_event.user_quote_amount_out;
47 pool_token_a_vault_amount = decoded_event.pool_base_token_reserves + swapped_amount_in;
49 pool_token_b_vault_amount = decoded_event.pool_quote_token_reserves
51 - swapped_amount_received
52 - decoded_event.protocol_fee
53 - decoded_event.coin_creator_fee;
54 let total_fee =
55 decoded_event.lp_fee + decoded_event.protocol_fee + decoded_event.coin_creator_fee;
56 fee_fraction_lp = if swapped_amount_received + total_fee == 0 {
59 0
60 } else {
61 (total_fee as u128 * LAMPORTS_PER_SOL / (swapped_amount_received + total_fee) as u128) as u64
62 };
63 }
64 else {
66
67 if
68 event_len == 416 ||
70 event_len == 401 ||
72 event_len == 431 {
74 let decoded_event =
75 PumpswapBuyEventIdl::try_from_slice(&swap_event_instruction.data[..401]).unwrap();
76 if event_len == 431 {
77 swapped_amount_in = decoded_event.quote_amount_in;
80 }
81 else {
82 swapped_amount_in = decoded_event.user_quote_amount_in;
83 }
84 swapped_amount_received = decoded_event.base_amount_out;
85 pool_token_b_vault_amount =
86 decoded_event.pool_quote_token_reserves + decoded_event.quote_amount_in_with_lp_fee;
87 pool_token_a_vault_amount = decoded_event.pool_base_token_reserves - swapped_amount_received;
88 let total_fee =
89 decoded_event.lp_fee + decoded_event.protocol_fee + decoded_event.coin_creator_fee;
90 fee_fraction_lp = if swapped_amount_in == 0 {
91 0
92 } else {
93 (total_fee as u128 * LAMPORTS_PER_SOL / swapped_amount_in as u128) as u64
94 };
95 }
96 else {
97 panic!(
98 "Pumpswap: Found a buy event, but data length {} is not recognized (expected 401 or 416), tx signature: {}",
99 event_len, signature
100 );
101 }
102 }
103
104 let price_a_b_lp =
105 pool_token_a_vault_amount as u128 * LAMPORTS_PER_SOL / pool_token_b_vault_amount as u128;
106 let price_b_a_lp =
107 pool_token_b_vault_amount as u128 * LAMPORTS_PER_SOL / pool_token_a_vault_amount as u128;
108
109 SwapTx {
110 pool: Pools::PumpswapAmm,
111 direction,
112 block_time,
113 slot,
114 index,
115 atomic_instruction_index,
116 fee_fraction_lp,
117 swapped_amount_in,
118 swapped_amount_received,
119 pool_token_a_vault_amount,
120 pool_token_b_vault_amount,
121 price_a_b_lp,
122 price_b_a_lp,
123 token_a_address,
124 token_b_address,
125 market_address,
126 signature: signature.clone(),
127 signers: signers.clone(),
128 }
129}