1use crate::gen::fiber as molecule_fiber;
2use crate::primitives::u8_32_as_byte_32;
3use ckb_types::packed::{OutPoint, Script};
4use ckb_types::prelude::Pack;
5use molecule::prelude::{Builder, Entity};
6use serde::{Deserialize, Serialize};
7use serde_with::serde_as;
8
9serde_with::serde_conv!(
11 ScriptHashTypeWrapper,
12 ckb_types::core::ScriptHashType,
13 |s: &ckb_types::core::ScriptHashType| -> String {
14 use ckb_types::core::ScriptHashType;
15 let v = match s {
16 ScriptHashType::Type => "type",
17 ScriptHashType::Data => "data",
18 ScriptHashType::Data1 => "data1",
19 ScriptHashType::Data2 => "data2",
20 _ => "unknown",
21 };
22 v.to_string()
23 },
24 |s: String| {
25 use ckb_types::core::ScriptHashType;
26 let v = match s.to_lowercase().as_str() {
27 "type" => ScriptHashType::Type,
28 "data" => ScriptHashType::Data,
29 "data1" => ScriptHashType::Data1,
30 "data2" => ScriptHashType::Data2,
31 _ => return Err("invalid hash type"),
32 };
33 Ok(v)
34 }
35);
36
37serde_with::serde_conv!(
38 DepTypeWrapper,
39 ckb_types::core::DepType,
40 |s: &ckb_types::core::DepType| -> String {
41 use ckb_types::core::DepType;
42 let v = match s {
43 DepType::Code => "code",
44 DepType::DepGroup => "dep_group",
45 };
46 v.to_string()
47 },
48 |s: String| {
49 let v = match s.to_lowercase().as_str() {
50 "code" => ckb_types::core::DepType::Code,
51 "dep_group" => ckb_types::core::DepType::DepGroup,
52 _ => return Err("invalid dep type"),
53 };
54 Ok(v)
55 }
56);
57
58#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, Hash)]
60pub struct UdtArgInfo {
61 pub name: String,
63 pub script: UdtScript,
65 pub auto_accept_amount: Option<u128>,
67 pub cell_deps: Vec<UdtDep>,
69}
70
71#[serde_as]
73#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, Hash, Default)]
74pub struct UdtScript {
75 pub code_hash: ckb_types::H256,
77 #[serde_as(as = "ScriptHashTypeWrapper")]
79 pub hash_type: ckb_types::core::ScriptHashType,
80 pub args: String,
82}
83
84#[serde_as]
86#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, Hash)]
87pub struct UdtCellDep {
88 pub out_point: ckb_jsonrpc_types::OutPoint,
90 #[serde_as(as = "DepTypeWrapper")]
92 pub dep_type: ckb_types::core::DepType,
93}
94
95#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, Hash)]
97pub struct UdtDep {
98 #[serde(default)]
100 pub cell_dep: Option<UdtCellDep>,
101 #[serde(default)]
103 pub type_id: Option<ckb_jsonrpc_types::Script>,
104}
105
106impl UdtDep {
107 pub fn with_cell_dep(cell_dep: UdtCellDep) -> Self {
109 Self {
110 cell_dep: Some(cell_dep),
111 type_id: None,
112 }
113 }
114
115 pub fn with_type_id(type_id: ckb_jsonrpc_types::Script) -> Self {
117 Self {
118 cell_dep: None,
119 type_id: Some(type_id),
120 }
121 }
122}
123
124#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, Hash, Default)]
126pub struct UdtCfgInfos(pub Vec<UdtArgInfo>);
127
128impl std::str::FromStr for UdtCfgInfos {
129 type Err = serde_json::Error;
130
131 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
132 serde_json::from_str(s)
133 }
134}
135
136impl From<UdtCfgInfos> for molecule_fiber::UdtCfgInfos {
139 fn from(udt_cfg_infos: UdtCfgInfos) -> Self {
140 molecule_fiber::UdtCfgInfos::new_builder()
141 .set(
142 udt_cfg_infos
143 .0
144 .into_iter()
145 .map(|udt_arg_info| udt_arg_info.into())
146 .collect(),
147 )
148 .build()
149 }
150}
151
152impl TryFrom<molecule_fiber::UdtCfgInfos> for UdtCfgInfos {
153 type Error = anyhow::Error;
154
155 fn try_from(udt_cfg_infos: molecule_fiber::UdtCfgInfos) -> Result<Self, Self::Error> {
156 Ok(UdtCfgInfos(
157 udt_cfg_infos
158 .into_iter()
159 .map(|udt_arg_info| udt_arg_info.try_into())
160 .collect::<Result<Vec<_>, _>>()?,
161 ))
162 }
163}
164
165impl From<UdtArgInfo> for molecule_fiber::UdtArgInfo {
168 fn from(udt_arg_info: UdtArgInfo) -> Self {
169 let builder = molecule_fiber::UdtArgInfo::new_builder()
170 .name(udt_arg_info.name.pack())
171 .script(udt_arg_info.script.into())
172 .cell_deps(
173 molecule_fiber::UdtCellDeps::new_builder()
174 .set(udt_arg_info.cell_deps.into_iter().map(Into::into).collect())
175 .build(),
176 );
177 let builder = if let Some(amount) = udt_arg_info.auto_accept_amount {
178 builder.auto_accept_amount(
179 molecule_fiber::Uint128Opt::new_builder()
180 .set(Some(amount.pack()))
181 .build(),
182 )
183 } else {
184 builder
185 };
186 builder.build()
187 }
188}
189
190impl TryFrom<molecule_fiber::UdtArgInfo> for UdtArgInfo {
191 type Error = anyhow::Error;
192
193 fn try_from(udt_arg_info: molecule_fiber::UdtArgInfo) -> Result<Self, Self::Error> {
194 use ckb_types::prelude::Unpack;
195 Ok(UdtArgInfo {
196 name: String::from_utf8(udt_arg_info.name().unpack()).unwrap_or_default(),
197 script: udt_arg_info.script().try_into()?,
198 auto_accept_amount: udt_arg_info
199 .auto_accept_amount()
200 .to_opt()
201 .map(|amount| amount.unpack()),
202 cell_deps: udt_arg_info
203 .cell_deps()
204 .into_iter()
205 .map(|cell_dep| cell_dep.try_into())
206 .collect::<Result<Vec<_>, _>>()?,
207 })
208 }
209}
210
211impl From<UdtScript> for molecule_fiber::UdtScript {
214 fn from(udt_script: UdtScript) -> Self {
215 use ckb_types::core::ScriptHashType;
216 let code_hash_bytes: [u8; 32] = udt_script.code_hash.into();
217 molecule_fiber::UdtScript::new_builder()
218 .code_hash(u8_32_as_byte_32(&code_hash_bytes))
219 .hash_type(
220 match udt_script.hash_type {
221 ScriptHashType::Type => 1u8,
222 ScriptHashType::Data => 0u8,
223 ScriptHashType::Data1 => 2u8,
224 ScriptHashType::Data2 => 4u8,
225 _ => panic!("unsupported hash type: {:?}", udt_script.hash_type),
226 }
227 .into(),
228 )
229 .args(udt_script.args.pack())
230 .build()
231 }
232}
233
234impl TryFrom<molecule_fiber::UdtScript> for UdtScript {
235 type Error = anyhow::Error;
236
237 fn try_from(udt_script: molecule_fiber::UdtScript) -> Result<Self, Self::Error> {
238 use ckb_types::core::ScriptHashType;
239 use ckb_types::prelude::Unpack;
240 let hash_type: u8 = udt_script.hash_type().into();
241 Ok(UdtScript {
242 code_hash: ckb_types::H256::from_slice(udt_script.code_hash().as_slice())?,
243 hash_type: match hash_type {
244 0 => ScriptHashType::Data,
245 1 => ScriptHashType::Type,
246 2 => ScriptHashType::Data1,
247 4 => ScriptHashType::Data2,
248 _ => return Err(anyhow::anyhow!("Invalid hash_type: {}", hash_type)),
249 },
250 args: String::from_utf8(udt_script.args().unpack()).unwrap_or_default(),
251 })
252 }
253}
254
255impl From<UdtDep> for molecule_fiber::UdtDep {
258 fn from(udt_dep: UdtDep) -> Self {
259 match udt_dep {
260 UdtDep {
261 cell_dep: Some(cell_dep),
262 type_id: None,
263 } => molecule_fiber::UdtDep::new_builder()
264 .set(molecule_fiber::UdtDepUnion::UdtCellDep(cell_dep.into()))
265 .build(),
266 UdtDep {
267 cell_dep: None,
268 type_id: Some(type_id),
269 } => molecule_fiber::UdtDep::new_builder()
270 .set(molecule_fiber::UdtDepUnion::Script(Script::from(type_id)))
271 .build(),
272 _ => panic!("UdtDep must have exactly one of cell_dep or type_id"),
273 }
274 }
275}
276
277impl TryFrom<molecule_fiber::UdtDep> for UdtDep {
278 type Error = anyhow::Error;
279
280 fn try_from(udt_dep: molecule_fiber::UdtDep) -> Result<Self, Self::Error> {
281 match udt_dep.to_enum() {
282 molecule_fiber::UdtDepUnion::UdtCellDep(cell_dep) => Ok(UdtDep {
283 cell_dep: Some(cell_dep.try_into()?),
284 type_id: None,
285 }),
286 molecule_fiber::UdtDepUnion::Script(type_id) => Ok(UdtDep {
287 cell_dep: None,
288 type_id: Some(type_id.into()),
289 }),
290 }
291 }
292}
293
294impl From<UdtCellDep> for molecule_fiber::UdtCellDep {
297 fn from(udt_cell_dep: UdtCellDep) -> Self {
298 use molecule::prelude::Entity;
299 molecule_fiber::UdtCellDep::new_builder()
300 .out_point(OutPoint::from(udt_cell_dep.out_point))
301 .dep_type(
302 match udt_cell_dep.dep_type {
303 ckb_types::core::DepType::Code => 0u8,
304 ckb_types::core::DepType::DepGroup => 1u8,
305 }
306 .into(),
307 )
308 .build()
309 }
310}
311
312impl TryFrom<molecule_fiber::UdtCellDep> for UdtCellDep {
313 type Error = anyhow::Error;
314
315 fn try_from(udt_cell_dep: molecule_fiber::UdtCellDep) -> Result<Self, Self::Error> {
316 let dep_type: u8 = udt_cell_dep.dep_type().into();
317 Ok(UdtCellDep {
318 out_point: udt_cell_dep.out_point().into(),
319 dep_type: match dep_type {
320 0 => ckb_types::core::DepType::Code,
321 1 => ckb_types::core::DepType::DepGroup,
322 _ => return Err(anyhow::anyhow!("Invalid dep_type: {}", dep_type)),
323 },
324 })
325 }
326}
327
328impl From<UdtCellDep> for ckb_types::packed::CellDep {
329 fn from(udt_cell_dep: UdtCellDep) -> Self {
330 let out_point: ckb_types::packed::OutPoint = udt_cell_dep.out_point.into();
331 ckb_types::packed::CellDep::new_builder()
332 .out_point(out_point)
333 .dep_type(udt_cell_dep.dep_type)
334 .build()
335 }
336}
337
338impl From<&UdtCellDep> for ckb_types::packed::CellDep {
339 fn from(udt_cell_dep: &UdtCellDep) -> Self {
340 let out_point: ckb_types::packed::OutPoint = udt_cell_dep.out_point.clone().into();
341 ckb_types::packed::CellDep::new_builder()
342 .out_point(out_point)
343 .dep_type(udt_cell_dep.dep_type)
344 .build()
345 }
346}
347
348impl TryFrom<ckb_types::packed::CellDep> for UdtCellDep {
349 type Error = anyhow::Error;
350
351 fn try_from(cell_dep: ckb_types::packed::CellDep) -> Result<Self, Self::Error> {
352 let dep_type: u8 = cell_dep.dep_type().into();
353 Ok(UdtCellDep {
354 out_point: cell_dep.out_point().into(),
355 dep_type: match dep_type {
356 0 => ckb_types::core::DepType::Code,
357 1 => ckb_types::core::DepType::DepGroup,
358 _ => return Err(anyhow::anyhow!("Invalid dep_type: {}", dep_type)),
359 },
360 })
361 }
362}