whisky_pallas/utils/
data.rs1use pallas_primitives::{BigInt, BoundedBytes, MaybeIndefArray, PlutusData};
2
3use serde_json::Value;
4use uplc::{Constr, KeyValuePairs};
5use whisky_common::WError;
6
7pub fn encode_json_str_to_plutus_datum(json: &str) -> Result<PlutusData, WError> {
8 let value: serde_json::Value = serde_json::from_str(json).map_err(WError::from_err(
9 "encode_json_str_to_plutus_datum - from_str",
10 ))?;
11
12 encode_json_value_to_plutus_datum(value)
13}
14
15pub fn encode_json_value_to_plutus_datum(value: Value) -> Result<PlutusData, WError> {
16 fn encode_number(x: serde_json::Number) -> Result<PlutusData, WError> {
17 if let Some(x) = x.as_u64() {
18 Ok(PlutusData::BigInt(BigInt::Int((x as i64).into())))
19 } else if let Some(x) = x.as_i64() {
20 Ok(PlutusData::BigInt(BigInt::Int(x.into())))
21 } else {
22 Err(WError::new(
23 "encode_number - ",
24 "floats not allowed in plutus datums",
25 ))
26 }
27 }
28
29 fn encode_string(s: &str, is_key: bool) -> Result<PlutusData, WError> {
30 if s.starts_with("0x") {
31 hex::decode(&s[2..])
32 .map(|bytes| PlutusData::BoundedBytes(BoundedBytes::from(bytes)))
33 .map_err(WError::from_err("encode_string - hex decode"))
34 } else if is_key {
35 if let Ok(x) = s.parse::<u64>() {
37 Ok(PlutusData::BigInt(BigInt::Int((x as i64).into())))
38 } else if let Ok(x) = s.parse::<i64>() {
39 Ok(PlutusData::BigInt(BigInt::Int(x.into())))
40 } else {
41 Ok(PlutusData::BoundedBytes(BoundedBytes::from(
43 s.as_bytes().to_vec(),
44 )))
45 }
46 } else {
47 Ok(PlutusData::BoundedBytes(BoundedBytes::from(
48 s.as_bytes().to_vec(),
49 )))
50 }
51 }
52
53 fn encode_array(json_arr: Vec<Value>) -> Result<PlutusData, WError> {
54 let mut arr: Vec<PlutusData> = Vec::new();
55 for item in json_arr {
56 arr.push(encode_json_value_to_plutus_datum(item)?);
57 }
58 Ok(PlutusData::Array(MaybeIndefArray::Def(arr)))
59 }
60
61 match value {
62 Value::Object(obj) => {
63 if obj.len() == 1 {
64 let (k, v) = obj.into_iter().next().unwrap();
65 match k.as_str() {
66 "int" => match v {
67 Value::Number(x) => encode_number(x),
68 _ => Err(WError::new(
69 "encode_json_value_to_plutus_datum - int",
70 "expected number for int type",
71 )),
72 },
73 "bytes" => match v {
74 Value::String(s) => encode_string(&s, false),
75 _ => Err(WError::new(
76 "encode_json_value_to_plutus_datum - bytes",
77 "expected string for bytes type",
78 )),
79 },
80 "list" => match v {
81 Value::Array(arr) => encode_array(arr),
82 _ => Err(WError::new(
83 "encode_json_value_to_plutus_datum - list",
84 "expected array for list type",
85 )),
86 },
87 "map" => match v {
88 Value::Array(map_vec) => {
89 let mut map: Vec<(PlutusData, PlutusData)> = vec![];
90 for entry in map_vec {
91 match entry {
92 Value::Object(entry_obj) => {
93 let raw_key = entry_obj.get("k").ok_or_else(|| {
94 WError::new(
95 "encode_json_value_to_plutus_datum - map entry",
96 "missing key in map entry",
97 )
98 })?;
99 let raw_value = entry_obj.get("v").ok_or_else(|| {
100 WError::new(
101 "encode_json_value_to_plutus_datum - map entry",
102 "missing value in map entry",
103 )
104 })?;
105 let encoded_key =
106 encode_json_value_to_plutus_datum(raw_key.clone())?;
107 let encoded_value =
108 encode_json_value_to_plutus_datum(raw_value.clone())?;
109 map.push((encoded_key, encoded_value));
110 }
111 _ => {
112 return Err(WError::new(
113 "encode_json_value_to_plutus_datum - map entry",
114 "expected object for map entry",
115 ))
116 }
117 }
118 }
119 Ok(PlutusData::Map(KeyValuePairs::from(map)))
120 }
121 _ => Err(WError::new(
122 "encode_json_value_to_plutus_datum - map",
123 "expected array for map type",
124 )),
125 },
126 _ => Err(WError::new(
127 "encode_json_value_to_plutus_datum",
128 "unknown type key",
129 )),
130 }
131 } else {
132 if obj.len() != 2 {
133 return Err(WError::new(
134 "encode_json_value_to_plutus_datum - constr",
135 "expected object with single key for constr type",
136 ));
137 }
138 let variant: u64 = obj
139 .get("constructor")
140 .ok_or_else(|| {
141 WError::new(
142 "encode_json_value_to_plutus_datum - constr",
143 "missing constr key for constr type",
144 )
145 })?
146 .as_u64()
147 .ok_or_else(|| {
148 WError::new(
149 "encode_json_value_to_plutus_datum - constr",
150 "expected unsigned integer for constr variant",
151 )
152 })?;
153 let fields_json = obj
154 .get("fields")
155 .ok_or_else(|| {
156 WError::new(
157 "encode_json_value_to_plutus_datum - constr",
158 "missing fields key for constr type",
159 )
160 })?
161 .as_array()
162 .ok_or_else(|| {
163 WError::new(
164 "encode_json_value_to_plutus_datum - constr",
165 "expected array for constr fields",
166 )
167 })?;
168 let mut fields: Vec<PlutusData> = Vec::new();
169 for field_json in fields_json {
170 fields.push(encode_json_value_to_plutus_datum(field_json.clone())?);
171 }
172 return Ok(PlutusData::Constr(Constr {
173 tag: variant + 121,
174 any_constructor: None,
175 fields: MaybeIndefArray::Def(fields),
176 }));
177 }
178 }
179 _ => {
180 return Err(WError::new(
181 "encode_json_value_to_plutus_datum",
182 "expected object with single key for typed value",
183 ))
184 }
185 }
186}