carbon_pumpfun_decoder/instructions/
mod.rs

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