1use alloc::collections::{btree_map::Values, BTreeMap};
10#[cfg(feature = "serde")]
11use core::fmt;
12use core::iter::Flatten;
13#[cfg(feature = "full-serde")]
14use std::io;
15
16#[cfg(feature = "serde")]
17use serde::{
18 de::{SeqAccess, Visitor},
19 ser::SerializeSeq,
20 Deserialize, Deserializer, Serialize, Serializer,
21};
22
23#[cfg(not(feature = "std"))]
24use crate::no_std_prelude::*;
25#[cfg(feature = "serde")]
26use crate::operation::Operation;
27use crate::{error::Error as AbiError, errors, Constructor, Error, Event, Function};
28
29#[derive(Clone, Debug, Default, PartialEq)]
31pub struct Contract {
32 pub constructor: Option<Constructor>,
34 pub functions: BTreeMap<String, Vec<Function>>,
36 pub events: BTreeMap<String, Vec<Event>>,
38 pub errors: BTreeMap<String, Vec<AbiError>>,
40 pub receive: bool,
42 pub fallback: bool,
44}
45
46#[cfg(feature = "serde")]
47impl<'a> Deserialize<'a> for Contract {
48 fn deserialize<D>(deserializer: D) -> Result<Contract, D::Error>
49 where
50 D: Deserializer<'a>,
51 {
52 deserializer.deserialize_any(ContractVisitor)
53 }
54}
55
56#[cfg(feature = "serde")]
57struct ContractVisitor;
58
59#[cfg(feature = "serde")]
60impl<'a> Visitor<'a> for ContractVisitor {
61 type Value = Contract;
62
63 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
64 formatter.write_str("valid abi spec file")
65 }
66
67 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
68 where
69 A: SeqAccess<'a>,
70 {
71 let mut result = Contract::default();
72 while let Some(operation) = seq.next_element()? {
73 match operation {
74 Operation::Constructor(constructor) => {
75 result.constructor = Some(constructor);
76 }
77 Operation::Function(func) => {
78 result.functions.entry(func.name.clone()).or_default().push(func);
79 }
80 Operation::Event(event) => {
81 result.events.entry(event.name.clone()).or_default().push(event);
82 }
83 Operation::Error(error) => {
84 result.errors.entry(error.name.clone()).or_default().push(error);
85 }
86 Operation::Fallback => {
87 result.fallback = true;
88 }
89 Operation::Receive => {
90 result.receive = true;
91 }
92 }
93 }
94
95 Ok(result)
96 }
97}
98
99#[cfg(feature = "serde")]
100impl Serialize for Contract {
101 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
102 where
103 S: Serializer,
104 {
105 #[derive(Serialize)]
107 #[serde(tag = "type")]
108 enum OperationRef<'a> {
109 #[serde(rename = "constructor")]
110 Constructor(&'a Constructor),
111
112 #[serde(rename = "function")]
113 Function(&'a Function),
114
115 #[serde(rename = "event")]
116 Event(&'a Event),
117
118 #[serde(rename = "error")]
119 Error(&'a AbiError),
120
121 #[serde(rename = "fallback")]
122 Fallback,
123
124 #[serde(rename = "receive")]
125 Receive,
126 }
127
128 let mut seq = serializer.serialize_seq(None)?;
129
130 if let Some(constructor) = &self.constructor {
131 seq.serialize_element(&OperationRef::Constructor(constructor))?;
132 }
133
134 for functions in self.functions.values() {
135 for function in functions {
136 seq.serialize_element(&OperationRef::Function(function))?;
137 }
138 }
139
140 for events in self.events.values() {
141 for event in events {
142 seq.serialize_element(&OperationRef::Event(event))?;
143 }
144 }
145
146 for errors in self.errors.values() {
147 for error in errors {
148 seq.serialize_element(&OperationRef::Error(error))?;
149 }
150 }
151
152 if self.receive {
153 seq.serialize_element(&OperationRef::Receive)?;
154 }
155
156 if self.fallback {
157 seq.serialize_element(&OperationRef::Fallback)?;
158 }
159
160 seq.end()
161 }
162}
163
164impl Contract {
165 #[cfg(feature = "full-serde")]
167 pub fn load<T: io::Read>(reader: T) -> errors::Result<Self> {
168 serde_json::from_reader(reader).map_err(From::from)
169 }
170
171 pub fn constructor(&self) -> Option<&Constructor> {
173 self.constructor.as_ref()
174 }
175
176 pub fn function(&self, name: &str) -> errors::Result<&Function> {
179 self.functions.get(name).into_iter().flatten().next().ok_or_else(|| Error::InvalidName(name.to_owned()))
180 }
181
182 pub fn event(&self, name: &str) -> errors::Result<&Event> {
184 self.events.get(name).into_iter().flatten().next().ok_or_else(|| Error::InvalidName(name.to_owned()))
185 }
186
187 pub fn error(&self, name: &str) -> errors::Result<&AbiError> {
189 self.errors.get(name).into_iter().flatten().next().ok_or_else(|| Error::InvalidName(name.to_owned()))
190 }
191
192 pub fn events_by_name(&self, name: &str) -> errors::Result<&Vec<Event>> {
194 self.events.get(name).ok_or_else(|| Error::InvalidName(name.to_owned()))
195 }
196
197 pub fn functions_by_name(&self, name: &str) -> errors::Result<&Vec<Function>> {
199 self.functions.get(name).ok_or_else(|| Error::InvalidName(name.to_owned()))
200 }
201
202 pub fn errors_by_name(&self, name: &str) -> errors::Result<&Vec<AbiError>> {
204 self.errors.get(name).ok_or_else(|| Error::InvalidName(name.to_owned()))
205 }
206
207 pub fn functions(&self) -> Functions {
209 Functions(self.functions.values().flatten())
210 }
211
212 pub fn events(&self) -> Events {
214 Events(self.events.values().flatten())
215 }
216
217 pub fn errors(&self) -> AbiErrors {
219 AbiErrors(self.errors.values().flatten())
220 }
221}
222
223pub struct Functions<'a>(Flatten<Values<'a, String, Vec<Function>>>);
225
226impl<'a> Iterator for Functions<'a> {
227 type Item = &'a Function;
228
229 fn next(&mut self) -> Option<Self::Item> {
230 self.0.next()
231 }
232}
233
234pub struct Events<'a>(Flatten<Values<'a, String, Vec<Event>>>);
236
237impl<'a> Iterator for Events<'a> {
238 type Item = &'a Event;
239
240 fn next(&mut self) -> Option<Self::Item> {
241 self.0.next()
242 }
243}
244
245pub struct AbiErrors<'a>(Flatten<Values<'a, String, Vec<AbiError>>>);
247
248impl<'a> Iterator for AbiErrors<'a> {
249 type Item = &'a AbiError;
250
251 fn next(&mut self) -> Option<Self::Item> {
252 self.0.next()
253 }
254}
255
256#[cfg(all(test, feature = "serde"))]
257#[allow(deprecated)]
258mod test {
259 #[cfg(not(feature = "std"))]
260 use crate::no_std_prelude::*;
261 use alloc::collections::BTreeMap;
262 use core::iter::FromIterator;
263
264 use crate::{tests::assert_ser_de, AbiError, Constructor, Contract, Event, EventParam, Function, Param, ParamType};
265
266 #[test]
267 fn empty() {
268 let json = "[]";
269
270 let deserialized: Contract = serde_json::from_str(json).unwrap();
271
272 assert_eq!(
273 deserialized,
274 Contract {
275 constructor: None,
276 functions: BTreeMap::new(),
277 events: BTreeMap::new(),
278 errors: BTreeMap::new(),
279 receive: false,
280 fallback: false,
281 }
282 );
283
284 assert_ser_de(&deserialized);
285 }
286
287 #[test]
288 fn constructor() {
289 let json = r#"
290 [
291 {
292 "type": "constructor",
293 "inputs": [
294 {
295 "name":"a",
296 "type":"address"
297 }
298 ]
299 }
300 ]
301 "#;
302
303 let deserialized: Contract = serde_json::from_str(json).unwrap();
304
305 assert_eq!(
306 deserialized,
307 Contract {
308 constructor: Some(Constructor {
309 inputs: vec![Param { name: "a".to_string(), kind: ParamType::Address, internal_type: None }]
310 }),
311 functions: BTreeMap::new(),
312 events: BTreeMap::new(),
313 errors: BTreeMap::new(),
314 receive: false,
315 fallback: false,
316 }
317 );
318
319 assert_ser_de(&deserialized);
320 }
321
322 #[test]
323 fn functions() {
324 let json = r#"
325 [
326 {
327 "type": "function",
328 "name": "foo",
329 "inputs": [
330 {
331 "name":"a",
332 "type":"address"
333 }
334 ],
335 "outputs": [
336 {
337 "name": "res",
338 "type":"address"
339 }
340 ]
341 },
342 {
343 "type": "function",
344 "name": "bar",
345 "inputs": [],
346 "outputs": []
347 }
348 ]
349 "#;
350
351 let deserialized: Contract = serde_json::from_str(json).unwrap();
352
353 assert_eq!(
354 deserialized,
355 Contract {
356 constructor: None,
357 functions: BTreeMap::from_iter(vec![
358 (
359 "foo".to_string(),
360 vec![Function {
361 name: "foo".to_string(),
362 inputs: vec![Param {
363 name: "a".to_string(),
364 kind: ParamType::Address,
365 internal_type: None,
366 }],
367 outputs: vec![Param {
368 name: "res".to_string(),
369 kind: ParamType::Address,
370 internal_type: None,
371 }],
372 constant: None,
373 state_mutability: Default::default(),
374 }]
375 ),
376 (
377 "bar".to_string(),
378 vec![Function {
379 name: "bar".to_string(),
380 inputs: vec![],
381 outputs: vec![],
382 constant: None,
383 state_mutability: Default::default(),
384 }]
385 ),
386 ]),
387 events: BTreeMap::new(),
388 errors: BTreeMap::new(),
389 receive: false,
390 fallback: false,
391 }
392 );
393
394 assert_ser_de(&deserialized);
395 }
396
397 #[test]
398 fn functions_overloads() {
399 let json = r#"
400 [
401 {
402 "type": "function",
403 "name": "foo",
404 "inputs": [
405 {
406 "name":"a",
407 "type":"address"
408 }
409 ],
410 "outputs": [
411 {
412 "name": "res",
413 "type":"address"
414 }
415 ]
416 },
417 {
418 "type": "function",
419 "name": "foo",
420 "inputs": [],
421 "outputs": []
422 }
423 ]
424 "#;
425
426 let deserialized: Contract = serde_json::from_str(json).unwrap();
427
428 assert_eq!(
429 deserialized,
430 Contract {
431 constructor: None,
432 functions: BTreeMap::from_iter(vec![(
433 "foo".to_string(),
434 vec![
435 Function {
436 name: "foo".to_string(),
437 inputs: vec![Param {
438 name: "a".to_string(),
439 kind: ParamType::Address,
440 internal_type: None,
441 }],
442 outputs: vec![Param {
443 name: "res".to_string(),
444 kind: ParamType::Address,
445 internal_type: None,
446 }],
447 constant: None,
448 state_mutability: Default::default(),
449 },
450 Function {
451 name: "foo".to_string(),
452 inputs: vec![],
453 outputs: vec![],
454 constant: None,
455 state_mutability: Default::default(),
456 },
457 ]
458 )]),
459 events: BTreeMap::new(),
460 errors: BTreeMap::new(),
461 receive: false,
462 fallback: false,
463 }
464 );
465
466 assert_ser_de(&deserialized);
467 }
468
469 #[test]
470 fn events() {
471 let json = r#"
472 [
473 {
474 "type": "event",
475 "name": "foo",
476 "inputs": [
477 {
478 "name":"a",
479 "type":"address"
480 }
481 ],
482 "anonymous": false
483 },
484 {
485 "type": "event",
486 "name": "bar",
487 "inputs": [
488 {
489 "name":"a",
490 "type":"address",
491 "indexed": true
492 }
493 ],
494 "anonymous": false
495 }
496 ]
497 "#;
498
499 let deserialized: Contract = serde_json::from_str(json).unwrap();
500
501 assert_eq!(
502 deserialized,
503 Contract {
504 constructor: None,
505 functions: BTreeMap::new(),
506 events: BTreeMap::from_iter(vec![
507 (
508 "foo".to_string(),
509 vec![Event {
510 name: "foo".to_string(),
511 inputs: vec![EventParam {
512 name: "a".to_string(),
513 kind: ParamType::Address,
514 indexed: false,
515 }],
516 anonymous: false,
517 }]
518 ),
519 (
520 "bar".to_string(),
521 vec![Event {
522 name: "bar".to_string(),
523 inputs: vec![EventParam { name: "a".to_string(), kind: ParamType::Address, indexed: true }],
524 anonymous: false,
525 }]
526 ),
527 ]),
528 errors: BTreeMap::new(),
529 receive: false,
530 fallback: false,
531 }
532 );
533
534 assert_ser_de(&deserialized);
535 }
536
537 #[test]
538 fn events_overload() {
539 let json = r#"
540 [
541 {
542 "type": "event",
543 "name": "foo",
544 "inputs": [
545 {
546 "name":"a",
547 "type":"address"
548 }
549 ],
550 "anonymous": false
551 },
552 {
553 "type": "event",
554 "name": "foo",
555 "inputs": [
556 {
557 "name":"a",
558 "type":"address",
559 "indexed": true
560 }
561 ],
562 "anonymous": false
563 }
564 ]
565 "#;
566
567 let deserialized: Contract = serde_json::from_str(json).unwrap();
568
569 assert_eq!(
570 deserialized,
571 Contract {
572 constructor: None,
573 functions: BTreeMap::new(),
574 events: BTreeMap::from_iter(vec![(
575 "foo".to_string(),
576 vec![
577 Event {
578 name: "foo".to_string(),
579 inputs: vec![EventParam {
580 name: "a".to_string(),
581 kind: ParamType::Address,
582 indexed: false,
583 }],
584 anonymous: false,
585 },
586 Event {
587 name: "foo".to_string(),
588 inputs: vec![EventParam { name: "a".to_string(), kind: ParamType::Address, indexed: true }],
589 anonymous: false,
590 },
591 ]
592 )]),
593 errors: BTreeMap::new(),
594 receive: false,
595 fallback: false,
596 }
597 );
598
599 assert_ser_de(&deserialized);
600 }
601
602 #[test]
603 fn errors() {
604 let json = r#"
605 [
606 {
607 "type": "error",
608 "inputs": [
609 {
610 "name": "available",
611 "type": "uint256"
612 },
613 {
614 "name": "required",
615 "type": "address"
616 }
617 ],
618 "name": "foo"
619 },
620 {
621 "type": "error",
622 "inputs": [
623 {
624 "name": "a",
625 "type": "uint256"
626 },
627 {
628 "name": "b",
629 "type": "address"
630 }
631 ],
632 "name": "bar"
633 }
634 ]
635 "#;
636
637 let deserialized: Contract = serde_json::from_str(json).unwrap();
638
639 assert_eq!(
640 deserialized,
641 Contract {
642 constructor: None,
643 functions: BTreeMap::new(),
644 events: BTreeMap::new(),
645 errors: BTreeMap::from_iter(vec![
646 (
647 "foo".to_string(),
648 vec![AbiError {
649 name: "foo".to_string(),
650 inputs: vec![
651 Param {
652 name: "available".to_string(),
653 kind: ParamType::Uint(256),
654 internal_type: None,
655 },
656 Param { name: "required".to_string(), kind: ParamType::Address, internal_type: None }
657 ],
658 }]
659 ),
660 (
661 "bar".to_string(),
662 vec![AbiError {
663 name: "bar".to_string(),
664 inputs: vec![
665 Param { name: "a".to_string(), kind: ParamType::Uint(256), internal_type: None },
666 Param { name: "b".to_string(), kind: ParamType::Address, internal_type: None }
667 ],
668 }]
669 ),
670 ]),
671 receive: false,
672 fallback: false,
673 }
674 );
675
676 assert_ser_de(&deserialized);
677 }
678
679 #[test]
680 fn errors_overload() {
681 let json = r#"
682 [
683 {
684 "type": "error",
685 "inputs": [
686 {
687 "name": "a",
688 "type": "uint256"
689 }
690 ],
691 "name": "foo"
692 },
693 {
694 "type": "error",
695 "inputs": [
696 {
697 "name": "a",
698 "type": "uint256"
699 },
700 {
701 "name": "b",
702 "type": "address"
703 }
704 ],
705 "name": "foo"
706 }
707 ]
708 "#;
709
710 let deserialized: Contract = serde_json::from_str(json).unwrap();
711
712 assert_eq!(
713 deserialized,
714 Contract {
715 constructor: None,
716 functions: BTreeMap::new(),
717 events: BTreeMap::new(),
718 errors: BTreeMap::from_iter(vec![(
719 "foo".to_string(),
720 vec![
721 AbiError {
722 name: "foo".to_string(),
723 inputs: vec![Param {
724 name: "a".to_string(),
725 kind: ParamType::Uint(256),
726 internal_type: None,
727 }],
728 },
729 AbiError {
730 name: "foo".to_string(),
731 inputs: vec![
732 Param { name: "a".to_string(), kind: ParamType::Uint(256), internal_type: None },
733 Param { name: "b".to_string(), kind: ParamType::Address, internal_type: None }
734 ],
735 },
736 ]
737 ),]),
738 receive: false,
739 fallback: false,
740 }
741 );
742
743 assert_ser_de(&deserialized);
744 }
745
746 #[test]
747 fn receive() {
748 let json = r#"
749 [
750 { "type": "receive" }
751 ]
752 "#;
753
754 let deserialized: Contract = serde_json::from_str(json).unwrap();
755
756 assert_eq!(
757 deserialized,
758 Contract {
759 constructor: None,
760 functions: BTreeMap::new(),
761 events: BTreeMap::new(),
762 errors: BTreeMap::new(),
763 receive: true,
764 fallback: false,
765 }
766 );
767
768 assert_ser_de(&deserialized);
769 }
770
771 #[test]
772 fn fallback() {
773 let json = r#"
774 [
775 { "type": "fallback" }
776 ]
777 "#;
778
779 let deserialized: Contract = serde_json::from_str(json).unwrap();
780
781 assert_eq!(
782 deserialized,
783 Contract {
784 constructor: None,
785 functions: BTreeMap::new(),
786 events: BTreeMap::new(),
787 errors: BTreeMap::new(),
788 receive: false,
789 fallback: true,
790 }
791 );
792
793 assert_ser_de(&deserialized);
794 }
795}