1use crate::spec::{ContractEvent, ContractType};
4use stellar_xdr::ScVal;
5
6#[derive(Debug, Clone, PartialEq, Eq)]
8pub struct DecodedValue {
9 pub raw: String,
11 pub abi_type: Option<String>,
13 pub label: String,
15}
16
17pub fn find_event_abi<'a>(
19 events: &'a [ContractEvent],
20 event_name: &'a str,
21) -> Option<&'a ContractEvent> {
22 events.iter().find(|e| e.name == event_name)
23}
24
25pub fn find_type_abi<'a>(
27 types: &'a [ContractType],
28 type_name: &'a str,
29) -> Option<&'a ContractType> {
30 types.iter().find(|t| t.name == type_name)
31}
32
33pub fn format_scval_abi(
35 val: &ScVal,
36 event_abi: Option<&[ContractEvent]>,
37 _types_abi: Option<&[ContractType]>,
38 event_hint: Option<&str>,
39) -> DecodedValue {
40 let raw_repr = format!("{:?}", val);
41 let raw_str = raw_repr.clone();
42
43 let label = match (event_hint, event_abi) {
44 (Some(name), Some(events)) => {
45 if find_event_abi(events, name).is_some() {
46 format!("event[{}] -> value", name)
47 } else {
48 raw_repr
49 }
50 }
51 _ => raw_repr,
52 };
53
54 DecodedValue {
55 raw: raw_str,
56 abi_type: None,
57 label,
58 }
59}
60
61#[cfg(test)]
62mod abi_tests {
63 use super::*;
64 use crate::spec::ContractEvent;
65 use stellar_xdr::ScVal;
66
67 fn dummy_events() -> Vec<ContractEvent> {
68 vec![ContractEvent {
69 name: "transfer".to_string(),
70 doc: "transfer event".to_string(),
71 params: vec![],
72 prefix_topics: vec![],
73 data_format: "single_value".to_string(),
74 }]
75 }
76
77 #[test]
78 fn format_scval_abi_with_event_hint() {
79 let events = dummy_events();
80 let val = ScVal::U32(42);
81 let result = format_scval_abi(&val, Some(&events), None, Some("transfer"));
82 assert!(result.label.contains("event[transfer]"));
83 }
84
85 #[test]
86 fn find_event_abi_exists() {
87 let events = dummy_events();
88 assert!(find_event_abi(&events, "transfer").is_some());
89 assert!(find_event_abi(&events, "unknown").is_none());
90 }
91}