1use starknet::core::types::contract::{
2 legacy::{RawLegacyEvent, RawLegacyStruct},
3 AbiEnum, AbiEventEnum, AbiEventStruct, AbiStruct, EventFieldKind,
4 StateMutability as StarknetStateMutability,
5};
6
7use crate::tokens::{CompositeInner, CompositeInnerKind, CompositeType, StateMutability, Token};
8use crate::Error;
9
10impl From<StarknetStateMutability> for StateMutability {
11 fn from(value: StarknetStateMutability) -> Self {
12 match value {
13 StarknetStateMutability::External => StateMutability::External,
14 StarknetStateMutability::View => StateMutability::View,
15 }
16 }
17}
18
19impl From<EventFieldKind> for CompositeInnerKind {
20 fn from(value: EventFieldKind) -> Self {
21 match value {
22 EventFieldKind::Key => CompositeInnerKind::Key,
23 EventFieldKind::Data => CompositeInnerKind::Data,
24 EventFieldKind::Nested => CompositeInnerKind::Nested,
25 EventFieldKind::Flat => CompositeInnerKind::Flat,
26 }
27 }
28}
29
30impl TryFrom<&AbiStruct> for Token {
31 type Error = Error;
32
33 fn try_from(value: &AbiStruct) -> Result<Self, Self::Error> {
34 let mut t = Token::parse(&value.name)?;
35
36 if let Token::Composite(ref mut c) = t {
37 c.r#type = CompositeType::Struct;
38
39 for (i, m) in value.members.iter().enumerate() {
40 c.inners.push(CompositeInner {
41 index: i,
42 name: m.name.clone(),
43 token: Token::parse(&m.r#type).unwrap(),
44 kind: CompositeInnerKind::NotUsed,
45 });
46 }
47
48 Ok(t)
49 } else {
50 Err(Error::ParsingFailed(format!(
51 "AbiStruct is expected to be a Composite token, got `{:?}`",
52 value,
53 )))
54 }
55 }
56}
57
58impl TryFrom<&AbiEnum> for Token {
59 type Error = Error;
60
61 fn try_from(value: &AbiEnum) -> Result<Self, Self::Error> {
62 let mut t = Token::parse(&value.name)?;
63
64 if t.type_name() == "option" {
65 return Ok(t);
66 }
67
68 if t.type_name() == "result" {
69 return Ok(t);
70 }
71
72 if let Token::Composite(ref mut c) = t {
73 c.r#type = CompositeType::Enum;
74
75 for (i, v) in value.variants.iter().enumerate() {
76 let kind = if v.r#type == "()" {
78 CompositeInnerKind::NotUsed
79 } else {
80 CompositeInnerKind::Data
81 };
82
83 c.inners.push(CompositeInner {
84 index: i,
85 name: v.name.clone(),
86 token: Token::parse(&v.r#type).unwrap(),
87 kind,
88 });
89 }
90
91 Ok(t)
92 } else {
93 Err(Error::ParsingFailed(format!(
94 "AbiEnum is expected to be a Composite token, got `{:?}`",
95 value,
96 )))
97 }
98 }
99}
100
101impl TryFrom<&AbiEventStruct> for Token {
102 type Error = Error;
103
104 fn try_from(value: &AbiEventStruct) -> Result<Self, Self::Error> {
105 let mut t = Token::parse(&value.name)?;
106
107 if let Token::Composite(ref mut c) = t {
108 c.r#type = CompositeType::Struct;
109 c.is_event = true;
110
111 for (i, m) in value.members.iter().enumerate() {
112 c.inners.push(CompositeInner {
113 index: i,
114 name: m.name.clone(),
115 token: Token::parse(&m.r#type).unwrap(),
116 kind: m.kind.clone().into(),
117 });
118 }
119
120 Ok(t)
121 } else {
122 Err(Error::ParsingFailed(format!(
123 "AbiEventStruct is expected to be a Composite token, got `{:?}`",
124 value,
125 )))
126 }
127 }
128}
129
130impl TryFrom<&AbiEventEnum> for Token {
131 type Error = Error;
132
133 fn try_from(value: &AbiEventEnum) -> Result<Self, Self::Error> {
134 let mut t = Token::parse(&value.name)?;
135
136 if let Token::Composite(ref mut c) = t {
137 c.r#type = CompositeType::Enum;
138 c.is_event = true;
139
140 for (i, v) in value.variants.iter().enumerate() {
141 c.inners.push(CompositeInner {
142 index: i,
143 name: v.name.clone(),
144 token: Token::parse(&v.r#type).unwrap(),
145 kind: v.kind.clone().into(),
146 });
147 }
148
149 Ok(t)
150 } else {
151 Err(Error::ParsingFailed(format!(
152 "AbiEventEnum is expected to be a Composite token, got `{:?}`",
153 value,
154 )))
155 }
156 }
157}
158
159impl TryFrom<&RawLegacyStruct> for Token {
160 type Error = Error;
161
162 fn try_from(value: &RawLegacyStruct) -> Result<Self, Self::Error> {
163 let mut t = Token::parse(&value.name)?;
164
165 if let Token::Composite(ref mut c) = t {
166 c.r#type = CompositeType::Struct;
167
168 for (i, m) in value.members.iter().enumerate() {
169 c.inners.push(CompositeInner {
170 index: i,
171 name: m.name.clone(),
172 token: Token::parse(&m.r#type).unwrap(),
173 kind: CompositeInnerKind::NotUsed,
174 });
175 }
176
177 Ok(t)
178 } else {
179 Err(Error::ParsingFailed(format!(
180 "RawLegacyStruct is expected to be a Composite token, got `{:?}`",
181 value,
182 )))
183 }
184 }
185}
186
187impl TryFrom<&RawLegacyEvent> for Token {
188 type Error = Error;
189
190 fn try_from(value: &RawLegacyEvent) -> Result<Self, Self::Error> {
191 let mut t = Token::parse(&value.name)?;
192
193 if let Token::Composite(ref mut c) = t {
194 c.r#type = CompositeType::Struct;
195 c.is_event = true;
196
197 let mut i = 0;
198
199 for m in value.data.iter() {
200 c.inners.push(CompositeInner {
201 index: i,
202 name: m.name.clone(),
203 token: Token::parse(&m.r#type).unwrap(),
204 kind: CompositeInnerKind::Data,
205 });
206
207 i += 1;
208 }
209
210 for m in value.keys.iter() {
211 c.inners.push(CompositeInner {
212 index: i,
213 name: m.name.clone(),
214 token: Token::parse(&m.r#type).unwrap(),
215 kind: CompositeInnerKind::Key,
216 });
217
218 i += 1;
219 }
220
221 Ok(t)
222 } else {
223 Err(Error::ParsingFailed(format!(
224 "RawLegacyEvent is expected to be a Composite token, got `{:?}`",
225 value,
226 )))
227 }
228 }
229}
230
231#[cfg(test)]
232mod tests {
233 use super::*;
234 use crate::tokens::CompositeType;
235 use crate::AbiParser;
236 use std::collections::HashMap;
237
238 #[test]
239 fn test_enum_variant_composite_inner_kind() {
240 let abi_json = r#"
242 [
243 {
244 "type": "enum",
245 "name": "test::TestEnum",
246 "variants": [
247 {
248 "name": "VariantWithoutData",
249 "type": "()"
250 },
251 {
252 "name": "VariantWithFelt252",
253 "type": "core::felt252"
254 },
255 {
256 "name": "VariantWithTuple",
257 "type": "(core::felt252, core::integer::u32)"
258 }
259 ]
260 }
261 ]
262 "#;
263
264 let result = AbiParser::tokens_from_abi_string(abi_json, &HashMap::new()).unwrap();
265
266 assert_eq!(result.enums.len(), 1);
267 let enum_composite = result.enums[0].to_composite().unwrap();
268
269 assert_eq!(enum_composite.r#type, CompositeType::Enum);
270 assert_eq!(enum_composite.inners.len(), 3);
271
272 assert_eq!(enum_composite.inners[0].name, "VariantWithoutData");
274 assert_eq!(enum_composite.inners[0].kind, CompositeInnerKind::NotUsed);
275
276 assert_eq!(enum_composite.inners[1].name, "VariantWithFelt252");
278 assert_eq!(enum_composite.inners[1].kind, CompositeInnerKind::Data);
279
280 assert_eq!(enum_composite.inners[2].name, "VariantWithTuple");
282 assert_eq!(enum_composite.inners[2].kind, CompositeInnerKind::Data);
283 }
284}