1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
use super::{Codegen, CodegenContext};
use crate::{format::gen_doc_string, CodeText};
use anyhow::*;
use move_idl::{IDLField, IDLStructType, IDLType};
pub fn serialize_arg(arg: &str, ty: &IDLType, ctx: &CodegenContext) -> Result<String> {
let ts_type = &ctx.generate(ty)?.to_string();
if ts_type.starts_with("ReadonlyArray") {
if let IDLType::Vector(inner) = ty {
let inner_arg = format!("inner_{}", arg.replace('.', "__"));
let inner_serialized = serialize_arg(&inner_arg, inner, ctx)?;
Ok(format!(
"{}.map(({}) => {})",
arg, inner_arg, inner_serialized
))
} else {
anyhow::bail!("Expected vector type for {}", arg)
}
} else {
let serializer = if ts_type == "p.U64" {
"p.serializers.u64"
} else if ts_type == "p.U128" {
"p.serializers.u128"
} else if ts_type == "p.HexStringArg"
|| ts_type == "p.RawAddress"
|| ts_type == "p.RawSigner"
|| ts_type == "p.ByteString"
{
"p.serializers.hexString"
} else {
return Ok(arg.to_string());
};
Ok(format!("{}({})", serializer, &arg))
}
}
fn generate_field_with_type_args(
ty: &IDLField,
ctx: &CodegenContext,
type_args: &[String],
parse_args: bool,
) -> Result<String> {
Ok(format!(
"{}{}: {};",
ty.doc
.as_ref()
.map(|doc| format!("\n{}", gen_doc_string(doc)))
.unwrap_or_default(),
ty.name,
generate_idl_type_with_type_args(&ty.ty, ctx, type_args, parse_args)?
))
}
fn generate_struct_with_type_args(
ty: &IDLStructType,
ctx: &CodegenContext,
type_args: &[String],
parse_args: bool,
) -> Result<String> {
let struct_def = ctx
.pkg
.structs
.iter()
.find(|sd| sd.name == ty.name)
.unwrap();
let fields_gen: CodeText = struct_def
.fields
.iter()
.map(|v| generate_field_with_type_args(v, ctx, type_args, parse_args))
.collect::<Result<Vec<_>>>()?
.join("\n")
.into();
Ok(format!("{{\n{}\n}}", fields_gen.trim().indent()))
}
pub(crate) fn generate_idl_type_with_type_args(
idl_type: &IDLType,
ctx: &CodegenContext,
type_args: &[String],
parse_args: bool,
) -> Result<String> {
let result = match idl_type {
IDLType::Bool => "boolean".to_string(),
IDLType::U8 => "number".to_string(),
IDLType::U64 => "p.U64".to_string(),
IDLType::U128 => "p.U128".to_string(),
IDLType::Address => "p.RawAddress".to_string(),
IDLType::Signer => "p.RawSigner".to_string(),
IDLType::Vector(inner) => match *inner.clone() {
IDLType::U8 => "p.ByteString".to_string(),
inner => format!(
"ReadonlyArray<{}>",
generate_idl_type_with_type_args(&inner, ctx, type_args, parse_args)?
),
},
IDLType::Struct(inner) => {
if inner.name.to_string() == *"0x1::ASCII::String"
|| inner.name.to_string() == *"0x1::string::String"
{
"string".to_string()
} else {
let next_type_args = inner
.ty_args
.iter()
.map(|arg| generate_idl_type_with_type_args(arg, ctx, type_args, parse_args))
.collect::<Result<Vec<_>>>()?;
generate_struct_with_type_args(inner, ctx, &next_type_args, parse_args)?
}
}
IDLType::TypeParam(v) => {
let result = type_args.get(*v as usize);
match result {
Some(v) => v.clone(),
None => "unknown".to_string(),
}
}
IDLType::Tuple(_) => todo!(),
};
if !parse_args && result.starts_with("p.") {
Ok("string".to_string())
} else {
Ok(result)
}
}
impl Codegen for IDLType {
fn generate_typescript(&self, ctx: &CodegenContext) -> Result<String> {
generate_idl_type_with_type_args(self, ctx, &[], true)
}
}