cainome_parser/abi/
parser_legacy.rs1use starknet::core::types::contract::legacy::{
2    RawLegacyAbiEntry, RawLegacyMember, RawLegacyStruct,
3};
4use starknet::core::types::contract::StateMutability;
5use std::collections::HashMap;
6
7use crate::tokens::{Composite, CompositeType, CoreBasic, Function, Token};
8use crate::{CainomeResult, Error, TokenizedAbi};
9
10pub struct AbiParserLegacy {}
11
12impl AbiParserLegacy {
13    pub fn tokens_from_abi_string(
20        abi: &str,
21        type_aliases: &HashMap<String, String>,
22    ) -> CainomeResult<TokenizedAbi> {
23        let abi_entries = Self::parse_abi_string(abi)?;
24        let tokenized_abi =
25            Self::collect_tokens(&abi_entries, type_aliases).expect("failed tokens parsing");
26
27        Ok(tokenized_abi)
28    }
29
30    pub fn parse_abi_string(abi: &str) -> CainomeResult<Vec<RawLegacyAbiEntry>> {
36        let entries =
37            serde_json::from_str::<Vec<RawLegacyAbiEntry>>(abi).map_err(Error::SerdeJson)?;
38        Ok(entries)
39    }
40
41    pub fn collect_tokens(
43        entries: &[RawLegacyAbiEntry],
44        type_aliases: &HashMap<String, String>,
45    ) -> CainomeResult<TokenizedAbi> {
46        let mut tokens: HashMap<String, Token> = HashMap::new();
47
48        for entry in entries {
49            Self::collect_entry_token(entry, &mut tokens)?;
50        }
51
52        let mut structs = vec![];
53        let mut enums = vec![];
54        let mut all_composites: HashMap<String, Composite> = HashMap::new();
58
59        for (_, mut t) in tokens {
61            for (type_path, alias) in type_aliases {
62                t.apply_alias(type_path, alias);
63            }
64
65            if let Token::Composite(ref c) = t {
66                all_composites.insert(c.type_path_no_generic(), c.clone());
67
68                match c.r#type {
69                    CompositeType::Struct => structs.push(t),
70                    CompositeType::Enum => enums.push(t),
71                    _ => (),
72                }
73            }
74        }
75
76        let mut functions = vec![];
77
78        for entry in entries {
79            Self::collect_entry_function(entry, &mut all_composites, &mut structs, &mut functions)?;
80        }
81
82        let interfaces: HashMap<String, Vec<Token>> = HashMap::new();
83
84        Ok(TokenizedAbi {
85            enums,
86            structs,
87            functions,
88            interfaces,
89        })
90    }
91
92    fn collect_entry_token(
99        entry: &RawLegacyAbiEntry,
100        tokens: &mut HashMap<String, Token>,
101    ) -> CainomeResult<()> {
102        match entry {
103            RawLegacyAbiEntry::Struct(s) => {
104                if CoreBasic::parse(&s.name).is_ok() {
106                    return Ok(());
107                };
108
109                let token: Token = s.try_into()?;
110                tokens.insert(token.type_path(), token);
111            }
112            RawLegacyAbiEntry::Event(ev) => {
113                let token: Token = ev.try_into()?;
114                tokens.insert(token.type_path(), token);
115            }
116            _ => (),
117        };
118
119        Ok(())
120    }
121
122    fn collect_entry_function(
131        entry: &RawLegacyAbiEntry,
132        all_composites: &mut HashMap<String, Composite>,
133        structs: &mut Vec<Token>,
134        functions: &mut Vec<Token>,
135    ) -> CainomeResult<()> {
136        fn get_existing_token_or_parsed(
139            type_path: &str,
140            all_composites: &HashMap<String, Composite>,
141        ) -> CainomeResult<Token> {
142            let parsed_token = Token::parse(type_path)?;
143
144            if let Token::Composite(ref c) = parsed_token {
148                match all_composites.get(&c.type_path_no_generic()) {
149                    Some(e) => Ok(Token::Composite(e.clone())),
150                    None => Ok(parsed_token),
151                }
152            } else {
153                Ok(parsed_token)
154            }
155        }
156
157        if let RawLegacyAbiEntry::Function(f) = entry {
160            let mutability = match f.state_mutability {
162                Some(_) => StateMutability::View,
163                None => StateMutability::External,
164            };
165
166            let mut func = Function::new(&f.name, mutability.into());
167
168            for i in &f.inputs {
169                let token = get_existing_token_or_parsed(&i.r#type, all_composites)?;
170                func.inputs.push((i.name.clone(), token));
171            }
172
173            for o in &f.outputs {
174                let token = get_existing_token_or_parsed(&o.r#type, all_composites)?;
175                func.named_outputs.push((o.name.clone(), token));
176            }
177
178            if !func.named_outputs.is_empty() {
179                let mut members = vec![];
180
181                for (offset, (n, t)) in func.named_outputs.iter().enumerate() {
182                    members.push(RawLegacyMember {
183                        name: n.clone(),
184                        offset: offset.try_into().unwrap(),
185                        r#type: t.type_path().clone(),
186                    });
187                }
188
189                let s = RawLegacyStruct {
190                    members,
191                    name: func.get_cairo0_output_name(),
192                    size: func.named_outputs.len() as u64,
193                };
194
195                structs.push((&s).try_into()?);
196            }
197
198            functions.push(Token::Function(func));
199        }
200
201        Ok(())
202    }
203}