1use schemars::JsonSchema;
4use serde::{Deserialize, Serialize};
5
6mod ty;
7pub use ty::NamedCLType;
8
9#[derive(Serialize, Deserialize, JsonSchema, Debug)]
11pub struct ContractSchema {
12 pub casper_contract_schema_version: u8,
13 pub toolchain: String,
14 pub authors: Vec<String>,
15 pub repository: Option<String>,
16 pub homepage: Option<String>,
17 pub contract_name: String,
18 pub contract_version: String,
19 pub types: Vec<CustomType>,
20 pub errors: Vec<UserError>,
21 pub entry_points: Vec<Entrypoint>,
22 pub events: Vec<Event>,
23 pub call: Option<CallMethod>,
24}
25
26impl ContractSchema {
27 pub fn as_json(&self) -> Option<String> {
29 serde_json::to_string_pretty(self).ok()
30 }
31}
32
33#[derive(Serialize, Deserialize, JsonSchema, Debug)]
35pub struct Entrypoint {
36 pub name: String,
37 pub description: Option<String>,
38 pub is_mutable: bool,
39 pub arguments: Vec<Argument>,
40 pub return_ty: Type,
41 pub is_contract_context: bool,
42 pub access: Access,
43}
44
45#[derive(Clone, Serialize, Deserialize, JsonSchema, Debug)]
47pub struct Argument {
48 pub name: String,
49 pub description: Option<String>,
50 pub ty: Type,
51 pub optional: bool,
52}
53
54impl Argument {
55 pub fn new(name: &str, description: &str, ty: NamedCLType) -> Self {
56 Self {
57 name: String::from(name),
58 description: parse_description(description),
59 ty: ty.into(),
60 optional: false,
61 }
62 }
63
64 pub fn new_opt(name: &str, description: &str, ty: NamedCLType) -> Self {
65 Self {
66 name: String::from(name),
67 description: parse_description(description),
68 ty: ty.into(),
69 optional: true,
70 }
71 }
72}
73
74#[derive(Serialize, Deserialize, JsonSchema, Debug)]
76#[serde(rename_all = "snake_case")]
77pub enum Access {
78 Public,
79 Groups(Vec<String>),
80}
81
82#[derive(
84 PartialEq, PartialOrd, Ord, Eq, Serialize, Deserialize, JsonSchema, Debug, Clone, Hash,
85)]
86pub struct StructMember {
87 pub name: String,
88 pub description: Option<String>,
89 pub ty: Type,
90}
91
92impl StructMember {
93 pub fn new(name: &str, description: &str, ty: NamedCLType) -> Self {
95 Self {
96 name: String::from(name),
97 description: parse_description(description),
98 ty: ty.into(),
99 }
100 }
101}
102
103fn parse_description(description: &str) -> Option<String> {
104 if description.is_empty() {
105 None
106 } else {
107 Some(String::from(description))
108 }
109}
110
111#[derive(
113 PartialEq, PartialOrd, Ord, Eq, Clone, Serialize, Deserialize, JsonSchema, Debug, Hash,
114)]
115#[serde(rename_all = "snake_case")]
116pub struct Type(pub NamedCLType);
117
118impl From<NamedCLType> for Type {
119 fn from(cl_type: NamedCLType) -> Self {
120 Self(cl_type)
121 }
122}
123
124#[derive(
126 PartialEq, PartialOrd, Ord, Eq, Clone, Serialize, Deserialize, JsonSchema, Debug, Hash,
127)]
128pub struct TypeName(pub String);
129
130impl From<&str> for TypeName {
131 fn from(name: &str) -> Self {
132 Self(String::from(name))
133 }
134}
135
136impl From<String> for TypeName {
137 fn from(name: String) -> Self {
138 Self(name)
139 }
140}
141
142impl TypeName {
143 pub fn new(name: &str) -> Self {
145 Self(String::from(name))
146 }
147}
148
149#[derive(
151 PartialEq, PartialOrd, Ord, Eq, Serialize, Deserialize, JsonSchema, Debug, Clone, Hash,
152)]
153#[serde(rename_all = "snake_case")]
154pub enum CustomType {
155 Struct {
156 name: TypeName,
157 description: Option<String>,
158 members: Vec<StructMember>,
159 },
160 Enum {
161 name: TypeName,
162 description: Option<String>,
163 variants: Vec<EnumVariant>,
164 },
165}
166
167impl CustomType {
168 pub fn name(&self) -> String {
170 match self {
171 CustomType::Struct { name, .. } => name.0.clone(),
172 CustomType::Enum { name, .. } => name.0.clone(),
173 }
174 }
175}
176
177#[derive(
179 PartialEq, PartialOrd, Ord, Eq, Serialize, Deserialize, JsonSchema, Debug, Clone, Hash,
180)]
181pub struct EnumVariant {
182 pub name: String,
183 pub description: Option<String>,
184 pub discriminant: u16,
185 pub ty: Type,
186}
187
188#[derive(PartialEq, PartialOrd, Ord, Eq, Serialize, Deserialize, JsonSchema, Debug)]
190pub struct Event {
191 pub name: String,
192 pub ty: TypeName,
193}
194
195impl Event {
196 pub fn new(name: &str, ty: &str) -> Self {
198 Self {
199 name: String::from(name),
200 ty: ty.into(),
201 }
202 }
203}
204
205#[derive(PartialEq, PartialOrd, Ord, Eq, Serialize, Deserialize, JsonSchema, Debug)]
207pub struct UserError {
208 pub name: String,
209 pub description: Option<String>,
210 pub discriminant: u16,
211}
212
213impl UserError {
214 pub fn new(name: &str, desc: &str, discriminant: u16) -> Self {
216 Self {
217 name: String::from(name),
218 description: parse_description(desc),
219 discriminant,
220 }
221 }
222}
223
224#[derive(Serialize, Deserialize, JsonSchema, Debug)]
226pub struct CallMethod {
227 pub wasm_file_name: String,
228 pub description: Option<String>,
229 pub arguments: Vec<Argument>,
230}
231
232impl CallMethod {
233 pub fn new(wasm_file_name: &str, description: &str, arguments: Vec<Argument>) -> Self {
235 Self {
236 wasm_file_name: String::from(wasm_file_name),
237 description: parse_description(description),
238 arguments,
239 }
240 }
241}