light_instruction_decoder/
registry.rs

1//! Instruction decoder registry for Light Protocol and common Solana programs
2
3use std::collections::HashMap;
4
5use solana_instruction::AccountMeta;
6use solana_pubkey::Pubkey;
7
8use crate::{DecodedInstruction, InstructionDecoder};
9
10// ============================================================================
11// Trait-based Decoder Registry
12// ============================================================================
13
14/// Registry of instruction decoders
15pub struct DecoderRegistry {
16    decoders: HashMap<Pubkey, Box<dyn InstructionDecoder>>,
17}
18
19impl std::fmt::Debug for DecoderRegistry {
20    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
21        f.debug_struct("DecoderRegistry")
22            .field("decoder_count", &self.decoders.len())
23            .field("program_ids", &self.decoders.keys().collect::<Vec<_>>())
24            .finish()
25    }
26}
27
28impl DecoderRegistry {
29    /// Create a new registry with built-in decoders
30    pub fn new() -> Self {
31        let mut registry = Self {
32            decoders: HashMap::new(),
33        };
34
35        // Register generic Solana program decoders (always available)
36        registry.register(Box::new(crate::programs::ComputeBudgetInstructionDecoder));
37        registry.register(Box::new(crate::programs::SplTokenInstructionDecoder));
38        registry.register(Box::new(crate::programs::Token2022InstructionDecoder));
39        registry.register(Box::new(crate::programs::SystemInstructionDecoder));
40
41        // Register Light Protocol decoders (requires light-protocol feature)
42        #[cfg(feature = "light-protocol")]
43        {
44            registry.register(Box::new(crate::programs::LightSystemInstructionDecoder));
45            registry.register(Box::new(
46                crate::programs::AccountCompressionInstructionDecoder,
47            ));
48            registry.register(Box::new(crate::programs::CTokenInstructionDecoder));
49            registry.register(Box::new(crate::programs::RegistryInstructionDecoder));
50        }
51
52        registry
53    }
54
55    /// Register a custom decoder
56    pub fn register(&mut self, decoder: Box<dyn InstructionDecoder>) {
57        self.decoders.insert(decoder.program_id(), decoder);
58    }
59
60    /// Register multiple decoders from a Vec
61    pub fn register_all(&mut self, decoders: Vec<Box<dyn InstructionDecoder>>) {
62        for decoder in decoders {
63            self.register(decoder);
64        }
65    }
66
67    /// Decode an instruction using registered decoders
68    pub fn decode(
69        &self,
70        program_id: &Pubkey,
71        data: &[u8],
72        accounts: &[AccountMeta],
73    ) -> Option<(DecodedInstruction, &dyn InstructionDecoder)> {
74        self.decoders.get(program_id).and_then(|decoder| {
75            decoder
76                .decode(data, accounts)
77                .map(|d| (d, decoder.as_ref()))
78        })
79    }
80
81    /// Get a decoder by program ID
82    pub fn get_decoder(&self, program_id: &Pubkey) -> Option<&dyn InstructionDecoder> {
83        self.decoders.get(program_id).map(|d| d.as_ref())
84    }
85
86    /// Check if a decoder exists for a program ID
87    pub fn has_decoder(&self, program_id: &Pubkey) -> bool {
88        self.decoders.contains_key(program_id)
89    }
90}
91
92impl Default for DecoderRegistry {
93    fn default() -> Self {
94        Self::new()
95    }
96}