casper_contract_schema/
lib.rs

1//! Data structures for the Casper Contract Schema.
2
3use schemars::JsonSchema;
4use serde::{Deserialize, Serialize};
5
6mod ty;
7pub use ty::NamedCLType;
8
9/// Contract definition.
10#[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    /// Returns the JSON representation of the contract schema.
28    pub fn as_json(&self) -> Option<String> {
29        serde_json::to_string_pretty(self).ok()
30    }
31}
32
33/// Entrypoint definition.
34#[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/// Entrypoint's argument definition.
46#[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/// Access control definition.
75#[derive(Serialize, Deserialize, JsonSchema, Debug)]
76#[serde(rename_all = "snake_case")]
77pub enum Access {
78    Public,
79    Groups(Vec<String>),
80}
81
82/// Struct member definition.
83#[derive(PartialEq, PartialOrd, Ord, Eq, Serialize, Deserialize, JsonSchema, Debug)]
84pub struct StructMember {
85    pub name: String,
86    pub description: Option<String>,
87    pub ty: Type,
88}
89
90impl StructMember {
91    /// Creates a new struct member.
92    pub fn new(name: &str, description: &str, ty: NamedCLType) -> Self {
93        Self {
94            name: String::from(name),
95            description: parse_description(description),
96            ty: ty.into(),
97        }
98    }
99}
100
101fn parse_description(description: &str) -> Option<String> {
102    if description.is_empty() {
103        None
104    } else {
105        Some(String::from(description))
106    }
107}
108
109/// Type definition.
110#[derive(PartialEq, PartialOrd, Ord, Eq, Clone, Serialize, Deserialize, JsonSchema, Debug)]
111#[serde(rename_all = "snake_case")]
112pub struct Type(pub NamedCLType);
113
114impl From<NamedCLType> for Type {
115    fn from(cl_type: NamedCLType) -> Self {
116        Self(cl_type)
117    }
118}
119
120/// Custom type name definition.
121#[derive(PartialEq, PartialOrd, Ord, Eq, Clone, Serialize, Deserialize, JsonSchema, Debug)]
122pub struct TypeName(pub String);
123
124impl From<&str> for TypeName {
125    fn from(name: &str) -> Self {
126        Self(String::from(name))
127    }
128}
129
130impl From<String> for TypeName {
131    fn from(name: String) -> Self {
132        Self(name)
133    }
134}
135
136impl TypeName {
137    /// Creates a new type name.
138    pub fn new(name: &str) -> Self {
139        Self(String::from(name))
140    }
141}
142
143/// Custom type definition. It covers structs and enums.
144#[derive(PartialEq, PartialOrd, Ord, Eq, Serialize, Deserialize, JsonSchema, Debug)]
145#[serde(rename_all = "snake_case")]
146pub enum CustomType {
147    Struct {
148        name: TypeName,
149        description: Option<String>,
150        members: Vec<StructMember>,
151    },
152    Enum {
153        name: TypeName,
154        description: Option<String>,
155        variants: Vec<EnumVariant>,
156    },
157}
158
159/// Enum variant definition.
160#[derive(PartialEq, PartialOrd, Ord, Eq, Serialize, Deserialize, JsonSchema, Debug)]
161pub struct EnumVariant {
162    pub name: String,
163    pub description: Option<String>,
164    pub discriminant: u16,
165    pub ty: Type,
166}
167
168/// Event definition.
169#[derive(PartialEq, PartialOrd, Ord, Eq, Serialize, Deserialize, JsonSchema, Debug)]
170pub struct Event {
171    pub name: String,
172    pub ty: TypeName,
173}
174
175impl Event {
176    /// Creates a new event.
177    pub fn new(name: &str, ty: &str) -> Self {
178        Self {
179            name: String::from(name),
180            ty: ty.into(),
181        }
182    }
183}
184
185/// User error definition.
186#[derive(PartialEq, PartialOrd, Ord, Eq, Serialize, Deserialize, JsonSchema, Debug)]
187pub struct UserError {
188    pub name: String,
189    pub description: Option<String>,
190    pub discriminant: u16,
191}
192
193impl UserError {
194    /// Creates a new user error variant.
195    pub fn new(name: &str, desc: &str, discriminant: u16) -> Self {
196        Self {
197            name: String::from(name),
198            description: parse_description(desc),
199            discriminant,
200        }
201    }
202}
203
204/// Call method definition.
205#[derive(Serialize, Deserialize, JsonSchema, Debug)]
206pub struct CallMethod {
207    pub wasm_file_name: String,
208    pub description: Option<String>,
209    pub arguments: Vec<Argument>,
210}
211
212impl CallMethod {
213    /// Creates a new call method definition.
214    pub fn new(wasm_file_name: &str, description: &str, arguments: Vec<Argument>) -> Self {
215        Self {
216            wasm_file_name: String::from(wasm_file_name),
217            description: parse_description(description),
218            arguments,
219        }
220    }
221}