carbon_pumpfun_decoder/instructions/
mod.rs

1use crate::PROGRAM_ID;
2
3use super::PumpfunDecoder;
4pub mod buy;
5pub mod complete_event;
6pub mod create;
7pub mod create_event;
8pub mod initialize;
9pub mod sell;
10pub mod set_params;
11pub mod set_params_event;
12pub mod trade_event;
13pub mod withdraw;
14
15#[derive(
16    carbon_core::InstructionType,
17    serde::Serialize,
18    serde::Deserialize,
19    PartialEq,
20    Eq,
21    Debug,
22    Clone,
23    Hash,
24)]
25pub enum PumpfunInstruction {
26    Buy(buy::Buy),
27    Create(create::Create),
28    Initialize(initialize::Initialize),
29    Sell(sell::Sell),
30    SetParams(set_params::SetParams),
31    Withdraw(withdraw::Withdraw),
32    CompleteEvent(complete_event::CompleteEvent),
33    CreateEvent(create_event::CreateEvent),
34    SetParamsEvent(set_params_event::SetParamsEvent),
35    TradeEvent(trade_event::TradeEvent),
36}
37
38impl carbon_core::instruction::InstructionDecoder<'_> for PumpfunDecoder {
39    type InstructionType = PumpfunInstruction;
40
41    fn decode_instruction(
42        &self,
43        instruction: &solana_instruction::Instruction,
44    ) -> Option<carbon_core::instruction::DecodedInstruction<Self::InstructionType>> {
45        if !instruction.program_id.eq(&PROGRAM_ID) {
46            return None;
47        }
48
49        carbon_core::try_decode_instructions!(instruction,
50            PumpfunInstruction::Buy => buy::Buy,
51            PumpfunInstruction::Create => create::Create,
52            PumpfunInstruction::Initialize => initialize::Initialize,
53            PumpfunInstruction::Sell => sell::Sell,
54            PumpfunInstruction::SetParams => set_params::SetParams,
55            PumpfunInstruction::Withdraw => withdraw::Withdraw,
56            PumpfunInstruction::CompleteEvent => complete_event::CompleteEvent,
57            PumpfunInstruction::CreateEvent => create_event::CreateEvent,
58            PumpfunInstruction::SetParamsEvent => set_params_event::SetParamsEvent,
59            PumpfunInstruction::TradeEvent => trade_event::TradeEvent,
60        )
61    }
62}
63
64#[cfg(test)]
65mod tests {
66    use carbon_core::{deserialize::ArrangeAccounts, instruction::InstructionDecoder};
67    use solana_instruction::AccountMeta;
68    use solana_pubkey::Pubkey;
69
70    use super::*;
71
72    #[test]
73    fn test_decode_buy() {
74        // Arrange
75        let expected_ix = PumpfunInstruction::Buy(buy::Buy {
76            amount: 2712969161192,
77            max_sol_cost: 204000000,
78        });
79        let expected_accounts = vec![
80            AccountMeta::new_readonly(
81                Pubkey::from_str_const("4wTV1YmiEkRvAtNtsSGPtUrqRYQMe5SKy2uB4Jjaxnjf"),
82                false,
83            ),
84            AccountMeta::new(
85                Pubkey::from_str_const("62qc2CNXwrYqQScmEdiZFFAnJR262PxWEuNQtxfafNgV"),
86                false,
87            ),
88            AccountMeta::new_readonly(
89                Pubkey::from_str_const("9p1PMtto471A7GvnRJVmDcuqUz3xDd1Lhu8vzrmpump"),
90                false,
91            ),
92            AccountMeta::new(
93                Pubkey::from_str_const("HWxwYxr4AV5ytUyT8pvjCEiUrXhwpbx365VpvQ6Bd6MZ"),
94                false,
95            ),
96            AccountMeta::new(
97                Pubkey::from_str_const("AUfg9aTAix7YarkHXSBMUyQPCTq55Gg1Z2NTe6utwwzG"),
98                false,
99            ),
100            AccountMeta::new(
101                Pubkey::from_str_const("4FLYmjhLuUb5ofNBo1PA9enF7HrPUSYUA1t55tUSFYa5"),
102                false,
103            ),
104            AccountMeta::new(
105                Pubkey::from_str_const("5ztadiszGPmBeGVcvmtPyqiHRA8SpU8mqNzPV1WeV88F"),
106                true,
107            ),
108            AccountMeta::new_readonly(
109                Pubkey::from_str_const("11111111111111111111111111111111"),
110                false,
111            ),
112            AccountMeta::new_readonly(
113                Pubkey::from_str_const("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"),
114                false,
115            ),
116            AccountMeta::new_readonly(
117                Pubkey::from_str_const("SysvarRent111111111111111111111111111111111"),
118                false,
119            ),
120            AccountMeta::new_readonly(
121                Pubkey::from_str_const("Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1"),
122                false,
123            ),
124            AccountMeta::new_readonly(
125                Pubkey::from_str_const("6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"),
126                false,
127            ),
128        ];
129        let expected_arranged_accounts = buy::BuyInstructionAccounts {
130            global: Pubkey::from_str_const("4wTV1YmiEkRvAtNtsSGPtUrqRYQMe5SKy2uB4Jjaxnjf"),
131            fee_recipient: Pubkey::from_str_const("62qc2CNXwrYqQScmEdiZFFAnJR262PxWEuNQtxfafNgV"),
132            mint: Pubkey::from_str_const("9p1PMtto471A7GvnRJVmDcuqUz3xDd1Lhu8vzrmpump"),
133            bonding_curve: Pubkey::from_str_const("HWxwYxr4AV5ytUyT8pvjCEiUrXhwpbx365VpvQ6Bd6MZ"),
134            associated_bonding_curve: Pubkey::from_str_const(
135                "AUfg9aTAix7YarkHXSBMUyQPCTq55Gg1Z2NTe6utwwzG",
136            ),
137            associated_user: Pubkey::from_str_const("4FLYmjhLuUb5ofNBo1PA9enF7HrPUSYUA1t55tUSFYa5"),
138            user: Pubkey::from_str_const("5ztadiszGPmBeGVcvmtPyqiHRA8SpU8mqNzPV1WeV88F"),
139            system_program: Pubkey::from_str_const("11111111111111111111111111111111"),
140            token_program: Pubkey::from_str_const("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"),
141            rent: Pubkey::from_str_const("SysvarRent111111111111111111111111111111111"),
142            event_authority: Pubkey::from_str_const("Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1"),
143            program: Pubkey::from_str_const("6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"),
144        };
145
146        // Act
147        let decoder = PumpfunDecoder;
148        let instruction = carbon_test_utils::read_instruction("tests/fixtures/buy_ix.json")
149            .expect("read fixture");
150        let decoded = decoder
151            .decode_instruction(&instruction)
152            .expect("decode instruction");
153        let decoded_arranged_accounts =
154            buy::Buy::arrange_accounts(&instruction.accounts).expect("aranage accounts");
155
156        // Assert
157        assert_eq!(decoded.data, expected_ix);
158        assert_eq!(decoded.accounts, expected_accounts);
159        assert_eq!(decoded.program_id, PROGRAM_ID);
160        assert_eq!(decoded_arranged_accounts, expected_arranged_accounts);
161    }
162
163    #[test]
164    fn test_decode_sell() {
165        // Arrange
166        let expected_ix = PumpfunInstruction::Sell(sell::Sell {
167            amount: 26705394300,
168            min_sol_output: 724522,
169        });
170        let expected_accounts = vec![
171            AccountMeta::new_readonly(
172                Pubkey::from_str_const("4wTV1YmiEkRvAtNtsSGPtUrqRYQMe5SKy2uB4Jjaxnjf"),
173                false,
174            ),
175            AccountMeta::new(
176                Pubkey::from_str_const("62qc2CNXwrYqQScmEdiZFFAnJR262PxWEuNQtxfafNgV"),
177                false,
178            ),
179            AccountMeta::new_readonly(
180                Pubkey::from_str_const("HXfFC4G1aJJo17KW56jJ2iaDLFXq6T8XZjPbQfhspump"),
181                false,
182            ),
183            AccountMeta::new(
184                Pubkey::from_str_const("8f12Y6z6CkMmcBqduvThRG2V873CP3eu2iBydqKGDX6y"),
185                false,
186            ),
187            AccountMeta::new(
188                Pubkey::from_str_const("GkSscwZJBhcFeB6hpWrnfrE73e5SawPmMuT55U1W4uqz"),
189                false,
190            ),
191            AccountMeta::new(
192                Pubkey::from_str_const("Bi6H7WPrZoJmqSauP38NuBaEttGraZkceR4p17ekoTwh"),
193                false,
194            ),
195            AccountMeta::new(
196                Pubkey::from_str_const("3bApZNQrP3T6Q1GvK1n1nUPHHnpnsbrEmdGyQyYLEbkP"),
197                true,
198            ),
199            AccountMeta::new_readonly(
200                Pubkey::from_str_const("11111111111111111111111111111111"),
201                false,
202            ),
203            AccountMeta::new_readonly(
204                Pubkey::from_str_const("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"),
205                false,
206            ),
207            AccountMeta::new_readonly(
208                Pubkey::from_str_const("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"),
209                false,
210            ),
211            AccountMeta::new_readonly(
212                Pubkey::from_str_const("Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1"),
213                false,
214            ),
215            AccountMeta::new_readonly(
216                Pubkey::from_str_const("6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"),
217                false,
218            ),
219        ];
220        let expected_arranged_accounts = sell::SellInstructionAccounts {
221            global: Pubkey::from_str_const("4wTV1YmiEkRvAtNtsSGPtUrqRYQMe5SKy2uB4Jjaxnjf"),
222            fee_recipient: Pubkey::from_str_const("62qc2CNXwrYqQScmEdiZFFAnJR262PxWEuNQtxfafNgV"),
223            mint: Pubkey::from_str_const("HXfFC4G1aJJo17KW56jJ2iaDLFXq6T8XZjPbQfhspump"),
224            bonding_curve: Pubkey::from_str_const("8f12Y6z6CkMmcBqduvThRG2V873CP3eu2iBydqKGDX6y"),
225            associated_bonding_curve: Pubkey::from_str_const(
226                "GkSscwZJBhcFeB6hpWrnfrE73e5SawPmMuT55U1W4uqz",
227            ),
228            associated_user: Pubkey::from_str_const("Bi6H7WPrZoJmqSauP38NuBaEttGraZkceR4p17ekoTwh"),
229            user: Pubkey::from_str_const("3bApZNQrP3T6Q1GvK1n1nUPHHnpnsbrEmdGyQyYLEbkP"),
230            system_program: Pubkey::from_str_const("11111111111111111111111111111111"),
231            associated_token_program: Pubkey::from_str_const(
232                "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL",
233            ),
234            token_program: Pubkey::from_str_const("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"),
235            event_authority: Pubkey::from_str_const("Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1"),
236            program: Pubkey::from_str_const("6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"),
237        };
238
239        // Act
240        let decoder = PumpfunDecoder;
241        let instruction = carbon_test_utils::read_instruction("tests/fixtures/sell_ix.json")
242            .expect("read fixture");
243        let decoded = decoder
244            .decode_instruction(&instruction)
245            .expect("decode instruction");
246        let decoded_arranged_accounts =
247            sell::Sell::arrange_accounts(&instruction.accounts).expect("aranage accounts");
248
249        // Assert
250        assert_eq!(decoded.data, expected_ix);
251        assert_eq!(decoded.accounts, expected_accounts);
252        assert_eq!(decoded.program_id, PROGRAM_ID);
253        assert_eq!(decoded_arranged_accounts, expected_arranged_accounts);
254    }
255
256    #[test]
257    fn test_decode_create() {
258        // Arrange
259        let expected_ix = PumpfunInstruction::Create(create::Create {
260            name: "Super Elon Bros ".to_owned(),
261            symbol: "SEB".to_owned(),
262            uri: "https://ipfs.io/ipfs/QmVnjMrWqhMBsmeFnaje87XVxMKY9y7BRL2DtFYJazTGM5".to_owned(),
263            creator: Pubkey::from_str_const("7a9xQF38YVW58TPeHavvXiVpqynCxY2GcohsZxdUZCX1"),
264        });
265        let expected_accounts = vec![
266            AccountMeta::new(
267                Pubkey::from_str_const("5PweXK19JD4PkafHm9BmpgiTaMoQgKq9EXVkDagwpump"),
268                true,
269            ),
270            AccountMeta::new_readonly(
271                Pubkey::from_str_const("TSLvdd1pWpHVjahSpsvCXUbgwsL3JAcvokwaKt1eokM"),
272                false,
273            ),
274            AccountMeta::new(
275                Pubkey::from_str_const("Chau1rGA8w4L43rAMUAKXGwq8hpPfGjUoHsiZJEyziKz"),
276                false,
277            ),
278            AccountMeta::new(
279                Pubkey::from_str_const("7JxriSri8PukwVQ6VQZ6ErpJ3Km1x6eWMnQeJ2Cd2148"),
280                false,
281            ),
282            AccountMeta::new_readonly(
283                Pubkey::from_str_const("4wTV1YmiEkRvAtNtsSGPtUrqRYQMe5SKy2uB4Jjaxnjf"),
284                false,
285            ),
286            AccountMeta::new_readonly(
287                Pubkey::from_str_const("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"),
288                false,
289            ),
290            AccountMeta::new(
291                Pubkey::from_str_const("Dzp1H2K6sNR8VAqXE9Q6eSdZckp7uQSJKR1FKY9SzFoS"),
292                false,
293            ),
294            AccountMeta::new(
295                Pubkey::from_str_const("7a9xQF38YVW58TPeHavvXiVpqynCxY2GcohsZxdUZCX1"),
296                true,
297            ),
298            AccountMeta::new_readonly(
299                Pubkey::from_str_const("11111111111111111111111111111111"),
300                false,
301            ),
302            AccountMeta::new_readonly(
303                Pubkey::from_str_const("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"),
304                false,
305            ),
306            AccountMeta::new_readonly(
307                Pubkey::from_str_const("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"),
308                false,
309            ),
310            AccountMeta::new_readonly(
311                Pubkey::from_str_const("SysvarRent111111111111111111111111111111111"),
312                false,
313            ),
314            AccountMeta::new_readonly(
315                Pubkey::from_str_const("Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1"),
316                false,
317            ),
318            AccountMeta::new_readonly(
319                Pubkey::from_str_const("6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"),
320                false,
321            ),
322        ];
323        let expected_arranged_accounts = create::CreateInstructionAccounts {
324            mint: Pubkey::from_str_const("5PweXK19JD4PkafHm9BmpgiTaMoQgKq9EXVkDagwpump"),
325            mint_authority: Pubkey::from_str_const("TSLvdd1pWpHVjahSpsvCXUbgwsL3JAcvokwaKt1eokM"),
326            bonding_curve: Pubkey::from_str_const("Chau1rGA8w4L43rAMUAKXGwq8hpPfGjUoHsiZJEyziKz"),
327            associated_bonding_curve: Pubkey::from_str_const(
328                "7JxriSri8PukwVQ6VQZ6ErpJ3Km1x6eWMnQeJ2Cd2148",
329            ),
330            global: Pubkey::from_str_const("4wTV1YmiEkRvAtNtsSGPtUrqRYQMe5SKy2uB4Jjaxnjf"),
331            mpl_token_metadata: Pubkey::from_str_const(
332                "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s",
333            ),
334            metadata: Pubkey::from_str_const("Dzp1H2K6sNR8VAqXE9Q6eSdZckp7uQSJKR1FKY9SzFoS"),
335            user: Pubkey::from_str_const("7a9xQF38YVW58TPeHavvXiVpqynCxY2GcohsZxdUZCX1"),
336            system_program: Pubkey::from_str_const("11111111111111111111111111111111"),
337            token_program: Pubkey::from_str_const("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"),
338            associated_token_program: Pubkey::from_str_const(
339                "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL",
340            ),
341            rent: Pubkey::from_str_const("SysvarRent111111111111111111111111111111111"),
342            event_authority: Pubkey::from_str_const("Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1"),
343            program: Pubkey::from_str_const("6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"),
344        };
345
346        // Act
347        let decoder = PumpfunDecoder;
348        let instruction = carbon_test_utils::read_instruction("tests/fixtures/create_ix.json")
349            .expect("read fixture");
350        let decoded = decoder
351            .decode_instruction(&instruction)
352            .expect("decode instruction");
353        let decoded_arranged_accounts =
354            create::Create::arrange_accounts(&instruction.accounts).expect("aranage accounts");
355
356        // Assert
357        assert_eq!(decoded.data, expected_ix);
358        assert_eq!(decoded.accounts, expected_accounts);
359        assert_eq!(decoded.program_id, PROGRAM_ID);
360        assert_eq!(decoded_arranged_accounts, expected_arranged_accounts);
361    }
362
363    #[test]
364    fn test_decode_withdraw() {
365        // Arrange
366        let expected_ix = PumpfunInstruction::Withdraw(withdraw::Withdraw {});
367        let expected_accounts = vec![
368            AccountMeta::new_readonly(
369                Pubkey::from_str_const("4wTV1YmiEkRvAtNtsSGPtUrqRYQMe5SKy2uB4Jjaxnjf"),
370                false,
371            ),
372            AccountMeta::new(
373                Pubkey::from_str_const("EGqbBGXmDA9QYd1XJkf3GDFoerQYeFW3FrQZZXRza9JL"),
374                false,
375            ),
376            AccountMeta::new_readonly(
377                Pubkey::from_str_const("8f8inBUeF6GCPQvN2qxu95uZMTjidZfS2RbYBrFSpump"),
378                false,
379            ),
380            AccountMeta::new(
381                Pubkey::from_str_const("DfcyEVHECKF9U14EzYqxeovufnndbN8qrDurVdJbkUwY"),
382                false,
383            ),
384            AccountMeta::new(
385                Pubkey::from_str_const("EQtzJCRiCpbEmKqZndvCQgGAXCFuGtP2FAZ2HYpH8F6F"),
386                false,
387            ),
388            AccountMeta::new(
389                Pubkey::from_str_const("7ngNZs9Ax61KJ8MKmQKFao73LB4jRRgrg4SZU3YsAbfY"),
390                false,
391            ),
392            AccountMeta::new(
393                Pubkey::from_str_const("39azUYFWPz3VHgKCf3VChUwbpURdCHRxjWVowf5jUJjg"),
394                true,
395            ),
396            AccountMeta::new_readonly(
397                Pubkey::from_str_const("11111111111111111111111111111111"),
398                false,
399            ),
400            AccountMeta::new_readonly(
401                Pubkey::from_str_const("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"),
402                false,
403            ),
404            AccountMeta::new_readonly(
405                Pubkey::from_str_const("SysvarRent111111111111111111111111111111111"),
406                false,
407            ),
408            AccountMeta::new_readonly(
409                Pubkey::from_str_const("Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1"),
410                false,
411            ),
412            AccountMeta::new_readonly(
413                Pubkey::from_str_const("6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"),
414                false,
415            ),
416        ];
417        let expected_arranged_accounts = withdraw::WithdrawInstructionAccounts {
418            global: Pubkey::from_str_const("4wTV1YmiEkRvAtNtsSGPtUrqRYQMe5SKy2uB4Jjaxnjf"),
419            last_withdraw: Pubkey::from_str_const("EGqbBGXmDA9QYd1XJkf3GDFoerQYeFW3FrQZZXRza9JL"),
420            mint: Pubkey::from_str_const("8f8inBUeF6GCPQvN2qxu95uZMTjidZfS2RbYBrFSpump"),
421            bonding_curve: Pubkey::from_str_const("DfcyEVHECKF9U14EzYqxeovufnndbN8qrDurVdJbkUwY"),
422            associated_bonding_curve: Pubkey::from_str_const(
423                "EQtzJCRiCpbEmKqZndvCQgGAXCFuGtP2FAZ2HYpH8F6F",
424            ),
425            associated_user: Pubkey::from_str_const("7ngNZs9Ax61KJ8MKmQKFao73LB4jRRgrg4SZU3YsAbfY"),
426            user: Pubkey::from_str_const("39azUYFWPz3VHgKCf3VChUwbpURdCHRxjWVowf5jUJjg"),
427            system_program: Pubkey::from_str_const("11111111111111111111111111111111"),
428            token_program: Pubkey::from_str_const("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"),
429            rent: Pubkey::from_str_const("SysvarRent111111111111111111111111111111111"),
430            event_authority: Pubkey::from_str_const("Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1"),
431            program: Pubkey::from_str_const("6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"),
432        };
433
434        // Act
435        let decoder = PumpfunDecoder;
436        let instruction = carbon_test_utils::read_instruction("tests/fixtures/withdraw_ix.json")
437            .expect("read fixture");
438        let decoded = decoder
439            .decode_instruction(&instruction)
440            .expect("decode instruction");
441        let decoded_arranged_accounts =
442            withdraw::Withdraw::arrange_accounts(&instruction.accounts).expect("aranage accounts");
443
444        // Assert
445        assert_eq!(decoded.data, expected_ix);
446        assert_eq!(decoded.accounts, expected_accounts);
447        assert_eq!(decoded.program_id, PROGRAM_ID);
448        assert_eq!(decoded_arranged_accounts, expected_arranged_accounts);
449    }
450}