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<'a> carbon_core::instruction::InstructionDecoder<'a> for PumpfunDecoder {
39 type InstructionType = PumpfunInstruction;
40
41 fn decode_instruction(
42 &self,
43 instruction: &solana_sdk::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_sdk::{instruction::AccountMeta, pubkey};
68
69 use super::*;
70
71 #[test]
72 fn test_decode_buy() {
73 let expected_ix = PumpfunInstruction::Buy(buy::Buy {
75 amount: 2712969161192,
76 max_sol_cost: 204000000,
77 });
78 let expected_accounts = vec![
79 AccountMeta::new_readonly(
80 pubkey!("4wTV1YmiEkRvAtNtsSGPtUrqRYQMe5SKy2uB4Jjaxnjf"),
81 false,
82 ),
83 AccountMeta::new(
84 pubkey!("62qc2CNXwrYqQScmEdiZFFAnJR262PxWEuNQtxfafNgV"),
85 false,
86 ),
87 AccountMeta::new_readonly(
88 pubkey!("9p1PMtto471A7GvnRJVmDcuqUz3xDd1Lhu8vzrmpump"),
89 false,
90 ),
91 AccountMeta::new(
92 pubkey!("HWxwYxr4AV5ytUyT8pvjCEiUrXhwpbx365VpvQ6Bd6MZ"),
93 false,
94 ),
95 AccountMeta::new(
96 pubkey!("AUfg9aTAix7YarkHXSBMUyQPCTq55Gg1Z2NTe6utwwzG"),
97 false,
98 ),
99 AccountMeta::new(
100 pubkey!("4FLYmjhLuUb5ofNBo1PA9enF7HrPUSYUA1t55tUSFYa5"),
101 false,
102 ),
103 AccountMeta::new(
104 pubkey!("5ztadiszGPmBeGVcvmtPyqiHRA8SpU8mqNzPV1WeV88F"),
105 true,
106 ),
107 AccountMeta::new_readonly(pubkey!("11111111111111111111111111111111"), false),
108 AccountMeta::new_readonly(
109 pubkey!("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"),
110 false,
111 ),
112 AccountMeta::new_readonly(
113 pubkey!("SysvarRent111111111111111111111111111111111"),
114 false,
115 ),
116 AccountMeta::new_readonly(
117 pubkey!("Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1"),
118 false,
119 ),
120 AccountMeta::new_readonly(
121 pubkey!("6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"),
122 false,
123 ),
124 ];
125 let expected_arranged_accounts = buy::BuyInstructionAccounts {
126 global: pubkey!("4wTV1YmiEkRvAtNtsSGPtUrqRYQMe5SKy2uB4Jjaxnjf"),
127 fee_recipient: pubkey!("62qc2CNXwrYqQScmEdiZFFAnJR262PxWEuNQtxfafNgV"),
128 mint: pubkey!("9p1PMtto471A7GvnRJVmDcuqUz3xDd1Lhu8vzrmpump"),
129 bonding_curve: pubkey!("HWxwYxr4AV5ytUyT8pvjCEiUrXhwpbx365VpvQ6Bd6MZ"),
130 associated_bonding_curve: pubkey!("AUfg9aTAix7YarkHXSBMUyQPCTq55Gg1Z2NTe6utwwzG"),
131 associated_user: pubkey!("4FLYmjhLuUb5ofNBo1PA9enF7HrPUSYUA1t55tUSFYa5"),
132 user: pubkey!("5ztadiszGPmBeGVcvmtPyqiHRA8SpU8mqNzPV1WeV88F"),
133 system_program: pubkey!("11111111111111111111111111111111"),
134 token_program: pubkey!("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"),
135 rent: pubkey!("SysvarRent111111111111111111111111111111111"),
136 event_authority: pubkey!("Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1"),
137 program: pubkey!("6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"),
138 };
139
140 let decoder = PumpfunDecoder;
142 let instruction = carbon_test_utils::read_instruction("tests/fixtures/buy_ix.json")
143 .expect("read fixture");
144 let decoded = decoder
145 .decode_instruction(&instruction)
146 .expect("decode instruction");
147 let decoded_arranged_accounts =
148 buy::Buy::arrange_accounts(&instruction.accounts).expect("aranage accounts");
149
150 assert_eq!(decoded.data, expected_ix);
152 assert_eq!(decoded.accounts, expected_accounts);
153 assert_eq!(decoded.program_id, PROGRAM_ID);
154 assert_eq!(decoded_arranged_accounts, expected_arranged_accounts);
155 }
156
157 #[test]
158 fn test_decode_sell() {
159 let expected_ix = PumpfunInstruction::Sell(sell::Sell {
161 amount: 26705394300,
162 min_sol_output: 724522,
163 });
164 let expected_accounts = vec![
165 AccountMeta::new_readonly(
166 pubkey!("4wTV1YmiEkRvAtNtsSGPtUrqRYQMe5SKy2uB4Jjaxnjf"),
167 false,
168 ),
169 AccountMeta::new(
170 pubkey!("62qc2CNXwrYqQScmEdiZFFAnJR262PxWEuNQtxfafNgV"),
171 false,
172 ),
173 AccountMeta::new_readonly(
174 pubkey!("HXfFC4G1aJJo17KW56jJ2iaDLFXq6T8XZjPbQfhspump"),
175 false,
176 ),
177 AccountMeta::new(
178 pubkey!("8f12Y6z6CkMmcBqduvThRG2V873CP3eu2iBydqKGDX6y"),
179 false,
180 ),
181 AccountMeta::new(
182 pubkey!("GkSscwZJBhcFeB6hpWrnfrE73e5SawPmMuT55U1W4uqz"),
183 false,
184 ),
185 AccountMeta::new(
186 pubkey!("Bi6H7WPrZoJmqSauP38NuBaEttGraZkceR4p17ekoTwh"),
187 false,
188 ),
189 AccountMeta::new(
190 pubkey!("3bApZNQrP3T6Q1GvK1n1nUPHHnpnsbrEmdGyQyYLEbkP"),
191 true,
192 ),
193 AccountMeta::new_readonly(pubkey!("11111111111111111111111111111111"), false),
194 AccountMeta::new_readonly(
195 pubkey!("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"),
196 false,
197 ),
198 AccountMeta::new_readonly(
199 pubkey!("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"),
200 false,
201 ),
202 AccountMeta::new_readonly(
203 pubkey!("Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1"),
204 false,
205 ),
206 AccountMeta::new_readonly(
207 pubkey!("6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"),
208 false,
209 ),
210 ];
211 let expected_arranged_accounts = sell::SellInstructionAccounts {
212 global: pubkey!("4wTV1YmiEkRvAtNtsSGPtUrqRYQMe5SKy2uB4Jjaxnjf"),
213 fee_recipient: pubkey!("62qc2CNXwrYqQScmEdiZFFAnJR262PxWEuNQtxfafNgV"),
214 mint: pubkey!("HXfFC4G1aJJo17KW56jJ2iaDLFXq6T8XZjPbQfhspump"),
215 bonding_curve: pubkey!("8f12Y6z6CkMmcBqduvThRG2V873CP3eu2iBydqKGDX6y"),
216 associated_bonding_curve: pubkey!("GkSscwZJBhcFeB6hpWrnfrE73e5SawPmMuT55U1W4uqz"),
217 associated_user: pubkey!("Bi6H7WPrZoJmqSauP38NuBaEttGraZkceR4p17ekoTwh"),
218 user: pubkey!("3bApZNQrP3T6Q1GvK1n1nUPHHnpnsbrEmdGyQyYLEbkP"),
219 system_program: pubkey!("11111111111111111111111111111111"),
220 associated_token_program: pubkey!("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"),
221 token_program: pubkey!("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"),
222 event_authority: pubkey!("Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1"),
223 program: pubkey!("6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"),
224 };
225
226 let decoder = PumpfunDecoder;
228 let instruction = carbon_test_utils::read_instruction("tests/fixtures/sell_ix.json")
229 .expect("read fixture");
230 let decoded = decoder
231 .decode_instruction(&instruction)
232 .expect("decode instruction");
233 let decoded_arranged_accounts =
234 sell::Sell::arrange_accounts(&instruction.accounts).expect("aranage accounts");
235
236 assert_eq!(decoded.data, expected_ix);
238 assert_eq!(decoded.accounts, expected_accounts);
239 assert_eq!(decoded.program_id, PROGRAM_ID);
240 assert_eq!(decoded_arranged_accounts, expected_arranged_accounts);
241 }
242
243 #[test]
244 fn test_decode_create() {
245 let expected_ix = PumpfunInstruction::Create(create::Create {
247 name: "Super Elon Bros ".to_owned(),
248 symbol: "SEB".to_owned(),
249 uri: "https://ipfs.io/ipfs/QmVnjMrWqhMBsmeFnaje87XVxMKY9y7BRL2DtFYJazTGM5".to_owned(),
250 creator: pubkey!("7a9xQF38YVW58TPeHavvXiVpqynCxY2GcohsZxdUZCX1"),
251 });
252 let expected_accounts = vec![
253 AccountMeta::new(
254 pubkey!("5PweXK19JD4PkafHm9BmpgiTaMoQgKq9EXVkDagwpump"),
255 true,
256 ),
257 AccountMeta::new_readonly(
258 pubkey!("TSLvdd1pWpHVjahSpsvCXUbgwsL3JAcvokwaKt1eokM"),
259 false,
260 ),
261 AccountMeta::new(
262 pubkey!("Chau1rGA8w4L43rAMUAKXGwq8hpPfGjUoHsiZJEyziKz"),
263 false,
264 ),
265 AccountMeta::new(
266 pubkey!("7JxriSri8PukwVQ6VQZ6ErpJ3Km1x6eWMnQeJ2Cd2148"),
267 false,
268 ),
269 AccountMeta::new_readonly(
270 pubkey!("4wTV1YmiEkRvAtNtsSGPtUrqRYQMe5SKy2uB4Jjaxnjf"),
271 false,
272 ),
273 AccountMeta::new_readonly(
274 pubkey!("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"),
275 false,
276 ),
277 AccountMeta::new(
278 pubkey!("Dzp1H2K6sNR8VAqXE9Q6eSdZckp7uQSJKR1FKY9SzFoS"),
279 false,
280 ),
281 AccountMeta::new(
282 pubkey!("7a9xQF38YVW58TPeHavvXiVpqynCxY2GcohsZxdUZCX1"),
283 true,
284 ),
285 AccountMeta::new_readonly(pubkey!("11111111111111111111111111111111"), false),
286 AccountMeta::new_readonly(
287 pubkey!("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"),
288 false,
289 ),
290 AccountMeta::new_readonly(
291 pubkey!("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"),
292 false,
293 ),
294 AccountMeta::new_readonly(
295 pubkey!("SysvarRent111111111111111111111111111111111"),
296 false,
297 ),
298 AccountMeta::new_readonly(
299 pubkey!("Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1"),
300 false,
301 ),
302 AccountMeta::new_readonly(
303 pubkey!("6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"),
304 false,
305 ),
306 ];
307 let expected_arranged_accounts = create::CreateInstructionAccounts {
308 mint: pubkey!("5PweXK19JD4PkafHm9BmpgiTaMoQgKq9EXVkDagwpump"),
309 mint_authority: pubkey!("TSLvdd1pWpHVjahSpsvCXUbgwsL3JAcvokwaKt1eokM"),
310 bonding_curve: pubkey!("Chau1rGA8w4L43rAMUAKXGwq8hpPfGjUoHsiZJEyziKz"),
311 associated_bonding_curve: pubkey!("7JxriSri8PukwVQ6VQZ6ErpJ3Km1x6eWMnQeJ2Cd2148"),
312 global: pubkey!("4wTV1YmiEkRvAtNtsSGPtUrqRYQMe5SKy2uB4Jjaxnjf"),
313 mpl_token_metadata: pubkey!("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"),
314 metadata: pubkey!("Dzp1H2K6sNR8VAqXE9Q6eSdZckp7uQSJKR1FKY9SzFoS"),
315 user: pubkey!("7a9xQF38YVW58TPeHavvXiVpqynCxY2GcohsZxdUZCX1"),
316 system_program: pubkey!("11111111111111111111111111111111"),
317 token_program: pubkey!("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"),
318 associated_token_program: pubkey!("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"),
319 rent: pubkey!("SysvarRent111111111111111111111111111111111"),
320 event_authority: pubkey!("Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1"),
321 program: pubkey!("6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"),
322 };
323
324 let decoder = PumpfunDecoder;
326 let instruction = carbon_test_utils::read_instruction("tests/fixtures/create_ix.json")
327 .expect("read fixture");
328 let decoded = decoder
329 .decode_instruction(&instruction)
330 .expect("decode instruction");
331 let decoded_arranged_accounts =
332 create::Create::arrange_accounts(&instruction.accounts).expect("aranage accounts");
333
334 assert_eq!(decoded.data, expected_ix);
336 assert_eq!(decoded.accounts, expected_accounts);
337 assert_eq!(decoded.program_id, PROGRAM_ID);
338 assert_eq!(decoded_arranged_accounts, expected_arranged_accounts);
339 }
340
341 #[test]
342 fn test_decode_withdraw() {
343 let expected_ix = PumpfunInstruction::Withdraw(withdraw::Withdraw {});
345 let expected_accounts = vec![
346 AccountMeta::new_readonly(
347 pubkey!("4wTV1YmiEkRvAtNtsSGPtUrqRYQMe5SKy2uB4Jjaxnjf"),
348 false,
349 ),
350 AccountMeta::new(
351 pubkey!("EGqbBGXmDA9QYd1XJkf3GDFoerQYeFW3FrQZZXRza9JL"),
352 false,
353 ),
354 AccountMeta::new_readonly(
355 pubkey!("8f8inBUeF6GCPQvN2qxu95uZMTjidZfS2RbYBrFSpump"),
356 false,
357 ),
358 AccountMeta::new(
359 pubkey!("DfcyEVHECKF9U14EzYqxeovufnndbN8qrDurVdJbkUwY"),
360 false,
361 ),
362 AccountMeta::new(
363 pubkey!("EQtzJCRiCpbEmKqZndvCQgGAXCFuGtP2FAZ2HYpH8F6F"),
364 false,
365 ),
366 AccountMeta::new(
367 pubkey!("7ngNZs9Ax61KJ8MKmQKFao73LB4jRRgrg4SZU3YsAbfY"),
368 false,
369 ),
370 AccountMeta::new(
371 pubkey!("39azUYFWPz3VHgKCf3VChUwbpURdCHRxjWVowf5jUJjg"),
372 true,
373 ),
374 AccountMeta::new_readonly(pubkey!("11111111111111111111111111111111"), false),
375 AccountMeta::new_readonly(
376 pubkey!("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"),
377 false,
378 ),
379 AccountMeta::new_readonly(
380 pubkey!("SysvarRent111111111111111111111111111111111"),
381 false,
382 ),
383 AccountMeta::new_readonly(
384 pubkey!("Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1"),
385 false,
386 ),
387 AccountMeta::new_readonly(
388 pubkey!("6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"),
389 false,
390 ),
391 ];
392 let expected_arranged_accounts = withdraw::WithdrawInstructionAccounts {
393 global: pubkey!("4wTV1YmiEkRvAtNtsSGPtUrqRYQMe5SKy2uB4Jjaxnjf"),
394 last_withdraw: pubkey!("EGqbBGXmDA9QYd1XJkf3GDFoerQYeFW3FrQZZXRza9JL"),
395 mint: pubkey!("8f8inBUeF6GCPQvN2qxu95uZMTjidZfS2RbYBrFSpump"),
396 bonding_curve: pubkey!("DfcyEVHECKF9U14EzYqxeovufnndbN8qrDurVdJbkUwY"),
397 associated_bonding_curve: pubkey!("EQtzJCRiCpbEmKqZndvCQgGAXCFuGtP2FAZ2HYpH8F6F"),
398 associated_user: pubkey!("7ngNZs9Ax61KJ8MKmQKFao73LB4jRRgrg4SZU3YsAbfY"),
399 user: pubkey!("39azUYFWPz3VHgKCf3VChUwbpURdCHRxjWVowf5jUJjg"),
400 system_program: pubkey!("11111111111111111111111111111111"),
401 token_program: pubkey!("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"),
402 rent: pubkey!("SysvarRent111111111111111111111111111111111"),
403 event_authority: pubkey!("Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1"),
404 program: pubkey!("6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"),
405 };
406
407 let decoder = PumpfunDecoder;
409 let instruction = carbon_test_utils::read_instruction("tests/fixtures/withdraw_ix.json")
410 .expect("read fixture");
411 let decoded = decoder
412 .decode_instruction(&instruction)
413 .expect("decode instruction");
414 let decoded_arranged_accounts =
415 withdraw::Withdraw::arrange_accounts(&instruction.accounts).expect("aranage accounts");
416
417 assert_eq!(decoded.data, expected_ix);
419 assert_eq!(decoded.accounts, expected_accounts);
420 assert_eq!(decoded.program_id, PROGRAM_ID);
421 assert_eq!(decoded_arranged_accounts, expected_arranged_accounts);
422 }
423}