carbon_moonshot_decoder/instructions/
mod.rs

1use crate::PROGRAM_ID;
2
3use super::MoonshotDecoder;
4pub mod buy;
5pub mod config_init;
6pub mod config_update;
7pub mod migrate_funds;
8pub mod migration_event;
9pub mod sell;
10pub mod token_mint;
11pub mod trade_event;
12
13#[derive(
14    carbon_core::InstructionType, serde::Serialize, serde::Deserialize, PartialEq, Eq, Debug, Clone,
15)]
16pub enum MoonshotInstruction {
17    TokenMint(token_mint::TokenMint),
18    Buy(buy::Buy),
19    Sell(sell::Sell),
20    MigrateFunds(migrate_funds::MigrateFunds),
21    ConfigInit(config_init::ConfigInit),
22    ConfigUpdate(config_update::ConfigUpdate),
23    TradeEvent(trade_event::TradeEvent),
24    MigrationEvent(migration_event::MigrationEvent),
25}
26
27impl carbon_core::instruction::InstructionDecoder<'_> for MoonshotDecoder {
28    type InstructionType = MoonshotInstruction;
29
30    fn decode_instruction(
31        &self,
32        instruction: &solana_instruction::Instruction,
33    ) -> Option<carbon_core::instruction::DecodedInstruction<Self::InstructionType>> {
34        if !instruction.program_id.eq(&PROGRAM_ID) {
35            return None;
36        }
37
38        carbon_core::try_decode_instructions!(instruction,
39            MoonshotInstruction::TokenMint => token_mint::TokenMint,
40            MoonshotInstruction::Buy => buy::Buy,
41            MoonshotInstruction::Sell => sell::Sell,
42            MoonshotInstruction::MigrateFunds => migrate_funds::MigrateFunds,
43            MoonshotInstruction::ConfigInit => config_init::ConfigInit,
44            MoonshotInstruction::ConfigUpdate => config_update::ConfigUpdate,
45            MoonshotInstruction::TradeEvent => trade_event::TradeEvent,
46            MoonshotInstruction::MigrationEvent => migration_event::MigrationEvent,
47        )
48    }
49}
50
51#[cfg(test)]
52mod tests {
53    use alloc::{string::ToString, vec};
54    use carbon_core::{
55        deserialize::{ArrangeAccounts, PrefixString},
56        instruction::InstructionDecoder,
57    };
58    use solana_instruction::AccountMeta;
59
60    use crate::types::{TokenMintParams, TradeParams};
61
62    use super::*;
63
64    #[test]
65    fn test_decode_token_mint() {
66        // Arrange
67        let expected_ix = MoonshotInstruction::TokenMint(token_mint::TokenMint {
68            mint_params: TokenMintParams {
69                name: PrefixString("Gamestop".to_string()),
70                symbol: PrefixString("$GME".to_string()),
71                uri: PrefixString(
72                    "https://cdn.dexscreener.com/cms/tokens/metadata/UgnNvayhAu8K97aoT3B8"
73                        .to_string(),
74                ),
75                decimals: 9,
76                collateral_currency: 0,
77                amount: 1000000000000000000,
78                curve_type: 1,
79                migration_target: 0,
80                ..TokenMintParams::default()
81            },
82        });
83        let expected_accounts = vec![
84            AccountMeta::new(
85                solana_pubkey::Pubkey::from_str_const(
86                    "AiG8HZSRociZpmHGmFnHQ3eQvFxVq4HUwxXcZKZJaEr1",
87                ),
88                true,
89            ),
90            AccountMeta::new_readonly(
91                solana_pubkey::Pubkey::from_str_const(
92                    "Cb8Fnhp95f9dLxB3sYkNCbN3Mjxuc3v2uQZ7uVeqvNGB",
93                ),
94                true,
95            ),
96            AccountMeta::new(
97                solana_pubkey::Pubkey::from_str_const(
98                    "ALPoEBuBD9GMWRQrMmWd81By5GCH8X9i9HiPWBf68n8C",
99                ),
100                false,
101            ),
102            AccountMeta::new(
103                solana_pubkey::Pubkey::from_str_const(
104                    "HkzfucJHWykNPSpKpduLVg2j45zafYhA1G51xPLumoon",
105                ),
106                true,
107            ),
108            AccountMeta::new(
109                solana_pubkey::Pubkey::from_str_const(
110                    "Do7VSKZ6yz1eJMg5N8GpZ5Me12jfXVTTaWTi6tgo3vFr",
111                ),
112                false,
113            ),
114            AccountMeta::new(
115                solana_pubkey::Pubkey::from_str_const(
116                    "6oGTJKhWPZQ1ixiguEDvbHQJLizqUmbyL9isRvNUEGR",
117                ),
118                false,
119            ),
120            AccountMeta::new_readonly(
121                solana_pubkey::Pubkey::from_str_const(
122                    "36Eru7v11oU5Pfrojyn5oY3nETA1a1iqsw2WUu6afkM9",
123                ),
124                false,
125            ),
126            AccountMeta::new_readonly(
127                solana_pubkey::Pubkey::from_str_const(
128                    "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
129                ),
130                false,
131            ),
132            AccountMeta::new_readonly(
133                solana_pubkey::Pubkey::from_str_const(
134                    "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL",
135                ),
136                false,
137            ),
138            AccountMeta::new_readonly(
139                solana_pubkey::Pubkey::from_str_const(
140                    "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s",
141                ),
142                false,
143            ),
144            AccountMeta::new_readonly(
145                solana_pubkey::Pubkey::from_str_const("11111111111111111111111111111111"),
146                false,
147            ),
148        ];
149        let expected_arranged_accounts = token_mint::TokenMintInstructionAccounts {
150            sender: solana_pubkey::Pubkey::from_str_const(
151                "AiG8HZSRociZpmHGmFnHQ3eQvFxVq4HUwxXcZKZJaEr1",
152            ),
153            backend_authority: solana_pubkey::Pubkey::from_str_const(
154                "Cb8Fnhp95f9dLxB3sYkNCbN3Mjxuc3v2uQZ7uVeqvNGB",
155            ),
156            curve_account: solana_pubkey::Pubkey::from_str_const(
157                "ALPoEBuBD9GMWRQrMmWd81By5GCH8X9i9HiPWBf68n8C",
158            ),
159            mint: solana_pubkey::Pubkey::from_str_const(
160                "HkzfucJHWykNPSpKpduLVg2j45zafYhA1G51xPLumoon",
161            ),
162            mint_metadata: solana_pubkey::Pubkey::from_str_const(
163                "Do7VSKZ6yz1eJMg5N8GpZ5Me12jfXVTTaWTi6tgo3vFr",
164            ),
165            curve_token_account: solana_pubkey::Pubkey::from_str_const(
166                "6oGTJKhWPZQ1ixiguEDvbHQJLizqUmbyL9isRvNUEGR",
167            ),
168            config_account: solana_pubkey::Pubkey::from_str_const(
169                "36Eru7v11oU5Pfrojyn5oY3nETA1a1iqsw2WUu6afkM9",
170            ),
171            token_program: solana_pubkey::Pubkey::from_str_const(
172                "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
173            ),
174            associated_token_program: solana_pubkey::Pubkey::from_str_const(
175                "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL",
176            ),
177            mpl_token_metadata: solana_pubkey::Pubkey::from_str_const(
178                "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s",
179            ),
180            system_program: solana_pubkey::Pubkey::from_str_const(
181                "11111111111111111111111111111111",
182            ),
183        };
184
185        // Act
186        let decoder = MoonshotDecoder;
187        let instruction = carbon_test_utils::read_instruction("tests/fixtures/token_mint_ix.json")
188            .expect("read fixture");
189        let decoded = decoder
190            .decode_instruction(&instruction)
191            .expect("decode instruction");
192        let decoded_arranged_accounts =
193            token_mint::TokenMint::arrange_accounts(&instruction.accounts)
194                .expect("aranage accounts");
195
196        // Assert
197        assert_eq!(decoded.data, expected_ix);
198        assert_eq!(decoded.accounts, expected_accounts);
199        assert_eq!(decoded.program_id, PROGRAM_ID);
200        assert_eq!(decoded_arranged_accounts, expected_arranged_accounts);
201    }
202
203    #[test]
204    fn test_decode_buy() {
205        // Arrange
206        let expected_ix = MoonshotInstruction::Buy(buy::Buy {
207            data: TradeParams {
208                token_amount: 5430576418647,
209                collateral_amount: 1640000,
210                fixed_side: 1,
211                slippage_bps: 9999,
212            },
213        });
214        let expected_accounts = vec![
215            AccountMeta::new(
216                solana_pubkey::Pubkey::from_str_const(
217                    "Ezug1uk7oTEULvBcXCngdZuJDmZ8Ed2TKY4oov4GmLLm",
218                ),
219                true,
220            ),
221            AccountMeta::new(
222                solana_pubkey::Pubkey::from_str_const(
223                    "6FqNPPA4W1nuvL1BHGhusSHjdNa4qJBoXyRKggAh9pb9",
224                ),
225                false,
226            ),
227            AccountMeta::new(
228                solana_pubkey::Pubkey::from_str_const(
229                    "4CYhuDhT4c9ATZpJceoQG8Du4vCjf5ZKvxsyXpJoVub4",
230                ),
231                false,
232            ),
233            AccountMeta::new(
234                solana_pubkey::Pubkey::from_str_const(
235                    "5Zg9kJdzYFKwS4hLzF1QvvNBYyUNpn9YWxYp6HVMknJt",
236                ),
237                false,
238            ),
239            AccountMeta::new(
240                solana_pubkey::Pubkey::from_str_const(
241                    "3udvfL24waJcLhskRAsStNMoNUvtyXdxrWQz4hgi953N",
242                ),
243                false,
244            ),
245            AccountMeta::new(
246                solana_pubkey::Pubkey::from_str_const(
247                    "5K5RtTWzzLp4P8Npi84ocf7F1vBsAu29N1irG4iiUnzt",
248                ),
249                false,
250            ),
251            AccountMeta::new_readonly(
252                solana_pubkey::Pubkey::from_str_const(
253                    "3cBFsM1wosTJi9yun6kcHhYHyJcut1MNQY28zjC4moon",
254                ),
255                false,
256            ),
257            AccountMeta::new_readonly(
258                solana_pubkey::Pubkey::from_str_const(
259                    "36Eru7v11oU5Pfrojyn5oY3nETA1a1iqsw2WUu6afkM9",
260                ),
261                false,
262            ),
263            AccountMeta::new_readonly(
264                solana_pubkey::Pubkey::from_str_const(
265                    "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
266                ),
267                false,
268            ),
269            AccountMeta::new_readonly(
270                solana_pubkey::Pubkey::from_str_const(
271                    "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL",
272                ),
273                false,
274            ),
275            AccountMeta::new_readonly(
276                solana_pubkey::Pubkey::from_str_const("11111111111111111111111111111111"),
277                false,
278            ),
279        ];
280        let expected_arranged_accounts = buy::BuyInstructionAccounts {
281            sender: solana_pubkey::Pubkey::from_str_const(
282                "Ezug1uk7oTEULvBcXCngdZuJDmZ8Ed2TKY4oov4GmLLm",
283            ),
284            sender_token_account: solana_pubkey::Pubkey::from_str_const(
285                "6FqNPPA4W1nuvL1BHGhusSHjdNa4qJBoXyRKggAh9pb9",
286            ),
287            curve_account: solana_pubkey::Pubkey::from_str_const(
288                "4CYhuDhT4c9ATZpJceoQG8Du4vCjf5ZKvxsyXpJoVub4",
289            ),
290            curve_token_account: solana_pubkey::Pubkey::from_str_const(
291                "5Zg9kJdzYFKwS4hLzF1QvvNBYyUNpn9YWxYp6HVMknJt",
292            ),
293            dex_fee: solana_pubkey::Pubkey::from_str_const(
294                "3udvfL24waJcLhskRAsStNMoNUvtyXdxrWQz4hgi953N",
295            ),
296            helio_fee: solana_pubkey::Pubkey::from_str_const(
297                "5K5RtTWzzLp4P8Npi84ocf7F1vBsAu29N1irG4iiUnzt",
298            ),
299            mint: solana_pubkey::Pubkey::from_str_const(
300                "3cBFsM1wosTJi9yun6kcHhYHyJcut1MNQY28zjC4moon",
301            ),
302            config_account: solana_pubkey::Pubkey::from_str_const(
303                "36Eru7v11oU5Pfrojyn5oY3nETA1a1iqsw2WUu6afkM9",
304            ),
305            token_program: solana_pubkey::Pubkey::from_str_const(
306                "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
307            ),
308            associated_token_program: solana_pubkey::Pubkey::from_str_const(
309                "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL",
310            ),
311            system_program: solana_pubkey::Pubkey::from_str_const(
312                "11111111111111111111111111111111",
313            ),
314        };
315
316        // Act
317        let decoder = MoonshotDecoder;
318        let instruction = carbon_test_utils::read_instruction("tests/fixtures/buy_ix.json")
319            .expect("read fixture");
320        let decoded = decoder
321            .decode_instruction(&instruction)
322            .expect("decode instruction");
323        let decoded_arranged_accounts =
324            buy::Buy::arrange_accounts(&instruction.accounts).expect("aranage accounts");
325
326        // Assert
327        assert_eq!(decoded.data, expected_ix);
328        assert_eq!(decoded.accounts, expected_accounts);
329        assert_eq!(decoded.program_id, PROGRAM_ID);
330        assert_eq!(decoded_arranged_accounts, expected_arranged_accounts);
331    }
332
333    #[test]
334    fn test_decode_sell() {
335        // Arrange
336        let expected_ix = MoonshotInstruction::Sell(sell::Sell {
337            data: TradeParams {
338                token_amount: 157227000000000,
339                collateral_amount: 20990579,
340                fixed_side: 0,
341                slippage_bps: 100,
342            },
343        });
344        let expected_accounts = vec![
345            AccountMeta::new(
346                solana_pubkey::Pubkey::from_str_const(
347                    "93fdoNBQF6t7aBPuPv3SGGpXyWmJVfvWPpPsBXrGqEK7",
348                ),
349                true,
350            ),
351            AccountMeta::new(
352                solana_pubkey::Pubkey::from_str_const(
353                    "H4QJQ3mm865pMW7Ufvq6BiSXn2P8xUCv2xFd1sWYpmmK",
354                ),
355                false,
356            ),
357            AccountMeta::new(
358                solana_pubkey::Pubkey::from_str_const(
359                    "DnTTm5JdDoZS9pY5JxxJJ9LUQx5L3MmcR5DdvHyEDruQ",
360                ),
361                false,
362            ),
363            AccountMeta::new(
364                solana_pubkey::Pubkey::from_str_const(
365                    "FNkJw68x21iyHrbA7yyUYyzFMmtdsNzxHWy7WwnaorEd",
366                ),
367                false,
368            ),
369            AccountMeta::new(
370                solana_pubkey::Pubkey::from_str_const(
371                    "3udvfL24waJcLhskRAsStNMoNUvtyXdxrWQz4hgi953N",
372                ),
373                false,
374            ),
375            AccountMeta::new(
376                solana_pubkey::Pubkey::from_str_const(
377                    "5K5RtTWzzLp4P8Npi84ocf7F1vBsAu29N1irG4iiUnzt",
378                ),
379                false,
380            ),
381            AccountMeta::new_readonly(
382                solana_pubkey::Pubkey::from_str_const(
383                    "3hrY3mte6rpea8UDSm4Be6D1sUJyLyLpGxFfRBvVmoon",
384                ),
385                false,
386            ),
387            AccountMeta::new_readonly(
388                solana_pubkey::Pubkey::from_str_const(
389                    "36Eru7v11oU5Pfrojyn5oY3nETA1a1iqsw2WUu6afkM9",
390                ),
391                false,
392            ),
393            AccountMeta::new_readonly(
394                solana_pubkey::Pubkey::from_str_const(
395                    "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
396                ),
397                false,
398            ),
399            AccountMeta::new_readonly(
400                solana_pubkey::Pubkey::from_str_const(
401                    "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL",
402                ),
403                false,
404            ),
405            AccountMeta::new_readonly(
406                solana_pubkey::Pubkey::from_str_const("11111111111111111111111111111111"),
407                false,
408            ),
409        ];
410        let expected_arranged_accounts = sell::SellInstructionAccounts {
411            sender: solana_pubkey::Pubkey::from_str_const(
412                "93fdoNBQF6t7aBPuPv3SGGpXyWmJVfvWPpPsBXrGqEK7",
413            ),
414            sender_token_account: solana_pubkey::Pubkey::from_str_const(
415                "H4QJQ3mm865pMW7Ufvq6BiSXn2P8xUCv2xFd1sWYpmmK",
416            ),
417            curve_account: solana_pubkey::Pubkey::from_str_const(
418                "DnTTm5JdDoZS9pY5JxxJJ9LUQx5L3MmcR5DdvHyEDruQ",
419            ),
420            curve_token_account: solana_pubkey::Pubkey::from_str_const(
421                "FNkJw68x21iyHrbA7yyUYyzFMmtdsNzxHWy7WwnaorEd",
422            ),
423            dex_fee: solana_pubkey::Pubkey::from_str_const(
424                "3udvfL24waJcLhskRAsStNMoNUvtyXdxrWQz4hgi953N",
425            ),
426            helio_fee: solana_pubkey::Pubkey::from_str_const(
427                "5K5RtTWzzLp4P8Npi84ocf7F1vBsAu29N1irG4iiUnzt",
428            ),
429            mint: solana_pubkey::Pubkey::from_str_const(
430                "3hrY3mte6rpea8UDSm4Be6D1sUJyLyLpGxFfRBvVmoon",
431            ),
432            config_account: solana_pubkey::Pubkey::from_str_const(
433                "36Eru7v11oU5Pfrojyn5oY3nETA1a1iqsw2WUu6afkM9",
434            ),
435            token_program: solana_pubkey::Pubkey::from_str_const(
436                "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
437            ),
438            associated_token_program: solana_pubkey::Pubkey::from_str_const(
439                "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL",
440            ),
441            system_program: solana_pubkey::Pubkey::from_str_const(
442                "11111111111111111111111111111111",
443            ),
444        };
445
446        // Act
447        let decoder = MoonshotDecoder;
448        let instruction = carbon_test_utils::read_instruction("tests/fixtures/sell_ix.json")
449            .expect("read fixture");
450        let decoded = decoder
451            .decode_instruction(&instruction)
452            .expect("decode instruction");
453        let decoded_arranged_accounts =
454            sell::Sell::arrange_accounts(&instruction.accounts).expect("aranage accounts");
455
456        // Assert
457        assert_eq!(decoded.data, expected_ix);
458        assert_eq!(decoded.accounts, expected_accounts);
459        assert_eq!(decoded.program_id, PROGRAM_ID);
460        assert_eq!(decoded_arranged_accounts, expected_arranged_accounts);
461    }
462
463    #[test]
464    fn test_decode_migrate_funds() {
465        // Arrange
466        let expected_ix = MoonshotInstruction::MigrateFunds(migrate_funds::MigrateFunds {});
467        let expected_accounts = vec![
468            AccountMeta::new_readonly(
469                solana_pubkey::Pubkey::from_str_const(
470                    "Cb8Fnhp95f9dLxB3sYkNCbN3Mjxuc3v2uQZ7uVeqvNGB",
471                ),
472                true,
473            ),
474            AccountMeta::new(
475                solana_pubkey::Pubkey::from_str_const(
476                    "CGsqR7CTqTwbmAUTPnfg9Bj9GLJgkrUD9rhjh3vHEYvh",
477                ),
478                true,
479            ),
480            AccountMeta::new(
481                solana_pubkey::Pubkey::from_str_const(
482                    "AwxvCNVa16VfZZdxtSZ2DJ8VDQ17J27FYMMJc9KoWkZt",
483                ),
484                false,
485            ),
486            AccountMeta::new(
487                solana_pubkey::Pubkey::from_str_const(
488                    "5JKuvPWQuYXAvvkCs7cvBFgmUdhPbaTW3ii7zGPknnHW",
489                ),
490                false,
491            ),
492            AccountMeta::new(
493                solana_pubkey::Pubkey::from_str_const(
494                    "HzxySmjxfbV8nthWw7qogXZ9qH4LFUxSZVpU91n48xFf",
495                ),
496                false,
497            ),
498            AccountMeta::new(
499                solana_pubkey::Pubkey::from_str_const(
500                    "5JZUMLtHBzG4PaQ6UAhVWnh2pZ1BMMKRWWpCbMxxe148",
501                ),
502                false,
503            ),
504            AccountMeta::new(
505                solana_pubkey::Pubkey::from_str_const(
506                    "3udvfL24waJcLhskRAsStNMoNUvtyXdxrWQz4hgi953N",
507                ),
508                false,
509            ),
510            AccountMeta::new(
511                solana_pubkey::Pubkey::from_str_const(
512                    "5K5RtTWzzLp4P8Npi84ocf7F1vBsAu29N1irG4iiUnzt",
513                ),
514                false,
515            ),
516            AccountMeta::new_readonly(
517                solana_pubkey::Pubkey::from_str_const(
518                    "36Eru7v11oU5Pfrojyn5oY3nETA1a1iqsw2WUu6afkM9",
519                ),
520                false,
521            ),
522            AccountMeta::new_readonly(
523                solana_pubkey::Pubkey::from_str_const("11111111111111111111111111111111"),
524                false,
525            ),
526            AccountMeta::new_readonly(
527                solana_pubkey::Pubkey::from_str_const(
528                    "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
529                ),
530                false,
531            ),
532            AccountMeta::new_readonly(
533                solana_pubkey::Pubkey::from_str_const(
534                    "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL",
535                ),
536                false,
537            ),
538        ];
539        let expected_arranged_accounts = migrate_funds::MigrateFundsInstructionAccounts {
540            backend_authority: solana_pubkey::Pubkey::from_str_const(
541                "Cb8Fnhp95f9dLxB3sYkNCbN3Mjxuc3v2uQZ7uVeqvNGB",
542            ),
543            migration_authority: solana_pubkey::Pubkey::from_str_const(
544                "CGsqR7CTqTwbmAUTPnfg9Bj9GLJgkrUD9rhjh3vHEYvh",
545            ),
546            curve_account: solana_pubkey::Pubkey::from_str_const(
547                "AwxvCNVa16VfZZdxtSZ2DJ8VDQ17J27FYMMJc9KoWkZt",
548            ),
549            curve_token_account: solana_pubkey::Pubkey::from_str_const(
550                "5JKuvPWQuYXAvvkCs7cvBFgmUdhPbaTW3ii7zGPknnHW",
551            ),
552            migration_authority_token_account: solana_pubkey::Pubkey::from_str_const(
553                "HzxySmjxfbV8nthWw7qogXZ9qH4LFUxSZVpU91n48xFf",
554            ),
555            mint: solana_pubkey::Pubkey::from_str_const(
556                "5JZUMLtHBzG4PaQ6UAhVWnh2pZ1BMMKRWWpCbMxxe148",
557            ),
558            dex_fee_account: solana_pubkey::Pubkey::from_str_const(
559                "3udvfL24waJcLhskRAsStNMoNUvtyXdxrWQz4hgi953N",
560            ),
561            helio_fee_account: solana_pubkey::Pubkey::from_str_const(
562                "5K5RtTWzzLp4P8Npi84ocf7F1vBsAu29N1irG4iiUnzt",
563            ),
564            config_account: solana_pubkey::Pubkey::from_str_const(
565                "36Eru7v11oU5Pfrojyn5oY3nETA1a1iqsw2WUu6afkM9",
566            ),
567            system_program: solana_pubkey::Pubkey::from_str_const(
568                "11111111111111111111111111111111",
569            ),
570            token_program: solana_pubkey::Pubkey::from_str_const(
571                "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
572            ),
573            associated_token_program: solana_pubkey::Pubkey::from_str_const(
574                "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL",
575            ),
576        };
577
578        // Act
579        let decoder = MoonshotDecoder;
580        let instruction =
581            carbon_test_utils::read_instruction("tests/fixtures/migrate_funds_ix.json")
582                .expect("read fixture");
583        let decoded = decoder
584            .decode_instruction(&instruction)
585            .expect("decode instruction");
586        let decoded_arranged_accounts =
587            migrate_funds::MigrateFunds::arrange_accounts(&instruction.accounts)
588                .expect("aranage accounts");
589
590        // Assert
591        assert_eq!(decoded.data, expected_ix);
592        assert_eq!(decoded.accounts, expected_accounts);
593        assert_eq!(decoded.program_id, PROGRAM_ID);
594        assert_eq!(decoded_arranged_accounts, expected_arranged_accounts);
595    }
596}