1use crate::error::{Error, Result};
2use crate::model::Base64String;
3use crate::util::JsonDeserializer;
4use serde_json::Value;
5use std::collections::HashMap;
6
7#[derive(Eq, PartialEq, Clone, Debug)]
8pub struct ScriptInfo {
9 script: Base64String,
10 complexity: u32,
11 verifier_complexity: u32,
12 callable_complexities: HashMap<String, u32>,
13 extra_fee: u64,
14 script_text: String,
15}
16
17impl ScriptInfo {
18 pub fn new(
19 script: Base64String,
20 complexity: u32,
21 verifier_complexity: u32,
22 callable_complexities: HashMap<String, u32>,
23 extra_fee: u64,
24 script_text: String,
25 ) -> ScriptInfo {
26 ScriptInfo {
27 script,
28 complexity,
29 verifier_complexity,
30 callable_complexities,
31 extra_fee,
32 script_text,
33 }
34 }
35
36 pub fn script(&self) -> Base64String {
37 self.script.clone()
38 }
39
40 pub fn complexity(&self) -> u32 {
41 self.complexity
42 }
43
44 pub fn verifier_complexity(&self) -> u32 {
45 self.verifier_complexity
46 }
47
48 pub fn callable_complexities(&self) -> HashMap<String, u32> {
49 self.callable_complexities.clone()
50 }
51
52 pub fn extra_fee(&self) -> u64 {
53 self.extra_fee
54 }
55
56 pub fn script_text(&self) -> String {
57 self.script_text.clone()
58 }
59}
60
61impl TryFrom<&Value> for ScriptInfo {
62 type Error = Error;
63
64 fn try_from(value: &Value) -> Result<Self> {
65 let script = Base64String::from_string(
66 &JsonDeserializer::safe_to_string_from_field(value, "script")
67 .unwrap_or_else(|_| "".to_owned()),
68 )?;
69 let complexity = JsonDeserializer::safe_to_int_from_field(value, "complexity")? as u32;
70 let verifier_complexity =
71 JsonDeserializer::safe_to_int_from_field(value, "verifierComplexity")? as u32;
72 let callable_complexities: HashMap<String, u32> =
73 JsonDeserializer::safe_to_map_from_field(value, "callableComplexities")?
74 .into_iter()
75 .map(|entry| {
76 Ok((
77 entry.0.to_owned(),
78 JsonDeserializer::safe_to_int(&entry.1)? as u32,
79 ))
80 })
81 .collect::<Result<HashMap<String, u32>>>()?;
82 let extra_fee = JsonDeserializer::safe_to_int_from_field(value, "extraFee")? as u64;
83 let script_text = JsonDeserializer::safe_to_string_from_field(value, "scriptText")
84 .unwrap_or_else(|_| "".to_owned());
85 Ok(ScriptInfo::new(
86 script,
87 complexity,
88 verifier_complexity,
89 callable_complexities,
90 extra_fee,
91 script_text,
92 ))
93 }
94}
95
96#[derive(Eq, PartialEq, Clone, Debug)]
97pub struct ScriptMeta {
98 meta_version: u32,
99 callable_functions: HashMap<String, Vec<ArgMeta>>,
100}
101
102impl ScriptMeta {
103 pub fn new(meta_version: u32, callable_functions: HashMap<String, Vec<ArgMeta>>) -> ScriptMeta {
104 ScriptMeta {
105 meta_version,
106 callable_functions,
107 }
108 }
109
110 pub fn meta_version(&self) -> u32 {
111 self.meta_version
112 }
113
114 pub fn callable_functions(&self) -> HashMap<String, Vec<ArgMeta>> {
115 self.callable_functions.clone()
116 }
117}
118
119impl TryFrom<&Value> for ScriptMeta {
120 type Error = Error;
121
122 fn try_from(value: &Value) -> Result<Self> {
123 let meta_version: u32 =
124 JsonDeserializer::safe_to_string_from_field(&value["meta"], "version")?
125 .parse()
126 .unwrap_or(0);
127 if meta_version == 0 {
128 return Ok(ScriptMeta::new(meta_version, HashMap::new()));
129 }
130 let callable_func_types =
131 JsonDeserializer::safe_to_map_from_field(&value["meta"], "callableFuncTypes")?;
132
133 let callable_functions: HashMap<String, Vec<ArgMeta>> = callable_func_types
134 .into_iter()
135 .map(|entry| {
136 let arg_meta = JsonDeserializer::safe_to_array(&entry.1)?
137 .iter()
138 .map(|arg| arg.try_into())
139 .collect::<Result<Vec<ArgMeta>>>()?;
140 Ok((entry.0, arg_meta))
141 })
142 .collect::<Result<HashMap<String, Vec<ArgMeta>>>>()?;
143 Ok(ScriptMeta::new(meta_version, callable_functions))
144 }
145}
146
147#[derive(Eq, PartialEq, Clone, Debug)]
148pub struct ArgMeta {
149 arg_name: String,
150 arg_type: String,
151}
152
153impl TryFrom<&Value> for ArgMeta {
154 type Error = Error;
155
156 fn try_from(value: &Value) -> Result<Self> {
157 let arg_name = JsonDeserializer::safe_to_string_from_field(value, "name")?;
158 let arg_type = JsonDeserializer::safe_to_string_from_field(value, "type")?;
159 Ok(ArgMeta::new(arg_name, arg_type))
160 }
161}
162
163impl ArgMeta {
164 pub fn new(arg_name: String, arg_type: String) -> ArgMeta {
165 ArgMeta { arg_name, arg_type }
166 }
167
168 pub fn arg_name(&self) -> String {
169 self.arg_name.clone()
170 }
171
172 pub fn arg_type(&self) -> String {
173 self.arg_type.clone()
174 }
175}
176
177#[cfg(test)]
178mod tests {
179 use crate::error::Result;
180 use crate::model::{ByteString, ScriptInfo, ScriptMeta};
181
182 use serde_json::Value;
183 use std::borrow::Borrow;
184 use std::fs;
185
186 #[test]
187 fn test_json_to_script_info() -> Result<()> {
188 let data = fs::read_to_string("./tests/resources/addresses/script_info_rs.json")
189 .expect("Unable to read file");
190 let json: Value = serde_json::from_str(&data).expect("failed to generate json from str");
191
192 let script_info: ScriptInfo = json.borrow().try_into()?;
193
194 assert_eq!(
195 script_info.script().encoded_with_prefix(),
196 "base64:AAIFAAAAAAAAAA=="
197 );
198 assert_eq!(script_info.complexity(), 14);
199 assert_eq!(script_info.verifier_complexity(), 0);
200 assert_eq!(script_info.callable_complexities()["storeData"], 14);
201 assert_eq!(script_info.extra_fee(), 0);
202 assert_eq!(
203 script_info.script_text(),
204 "DApp(DAppMeta(2,Vector(CallableFuncSignature))"
205 );
206 Ok(())
207 }
208
209 #[test]
210 fn test_json_to_script_meta() -> Result<()> {
211 let data = fs::read_to_string("./tests/resources/addresses/script_meta_rs.json")
212 .expect("Unable to read file");
213 let json: Value = serde_json::from_str(&data).expect("failed to generate json from str");
214
215 let script_meta: ScriptMeta = json.borrow().try_into()?;
216
217 assert_eq!(script_meta.meta_version(), 2);
218 let function_args_meta = &script_meta.callable_functions()["storeData"];
219
220 assert_eq!(function_args_meta[0].arg_type, "Boolean");
221 assert_eq!(function_args_meta[0].arg_name, "bool");
222
223 assert_eq!(function_args_meta[1].arg_type, "String");
224 assert_eq!(function_args_meta[1].arg_name, "string");
225
226 assert_eq!(function_args_meta[2].arg_type, "Int");
227 assert_eq!(function_args_meta[2].arg_name, "integer");
228
229 assert_eq!(function_args_meta[3].arg_type, "ByteVector");
230 assert_eq!(function_args_meta[3].arg_name, "binary");
231
232 assert_eq!(function_args_meta[4].arg_type, "List[Int]");
233 assert_eq!(function_args_meta[4].arg_name, "list");
234
235 Ok(())
236 }
237}