codama_nodes/
program_node.rs

1use crate::{
2    AccountNode, CamelCaseString, DefinedTypeNode, Docs, ErrorNode, HasName, InstructionNode,
3    PdaNode,
4};
5use codama_nodes_derive::node;
6
7#[node]
8#[derive(Default)]
9pub struct ProgramNode {
10    // Data.
11    pub name: CamelCaseString,
12    pub public_key: String,
13    pub version: String,
14    #[serde(skip_serializing_if = "crate::is_default")]
15    pub origin: Option<String>, // 'anchor' | 'shank'. Soon to be deprecated.
16    #[serde(default, skip_serializing_if = "crate::is_default")]
17    pub docs: Docs,
18
19    // Children.
20    #[serde(default)]
21    pub accounts: Vec<AccountNode>,
22    #[serde(default)]
23    pub instructions: Vec<InstructionNode>,
24    #[serde(default)]
25    pub defined_types: Vec<DefinedTypeNode>,
26    #[serde(default)]
27    pub pdas: Vec<PdaNode>,
28    #[serde(default)]
29    pub errors: Vec<ErrorNode>,
30}
31
32impl ProgramNode {
33    pub fn new<T: Into<CamelCaseString>, U: Into<String>>(name: T, public_key: U) -> Self {
34        Self {
35            name: name.into(),
36            public_key: public_key.into(),
37            ..Default::default()
38        }
39    }
40
41    pub fn set_version<T: Into<String>>(mut self, version: T) -> Self {
42        self.version = version.into();
43        self
44    }
45
46    pub fn add_account(mut self, account: AccountNode) -> Self {
47        self.accounts.push(account);
48        self
49    }
50
51    pub fn add_instruction(mut self, instruction: InstructionNode) -> Self {
52        self.instructions.push(instruction);
53        self
54    }
55
56    pub fn add_defined_type(mut self, defined_type: DefinedTypeNode) -> Self {
57        self.defined_types.push(defined_type);
58        self
59    }
60
61    pub fn add_pda(mut self, pda: PdaNode) -> Self {
62        self.pdas.push(pda);
63        self
64    }
65
66    pub fn add_error(mut self, error: ErrorNode) -> Self {
67        self.errors.push(error);
68        self
69    }
70}
71
72impl HasName for ProgramNode {
73    fn name(&self) -> &CamelCaseString {
74        &self.name
75    }
76}
77
78#[cfg(test)]
79mod tests {
80    use super::*;
81    use pretty_assertions::assert_eq;
82
83    #[test]
84    fn new() {
85        let node = ProgramNode::new("my_program", "1234..5678");
86        assert_eq!(node.name, CamelCaseString::new("myProgram"));
87        assert_eq!(node.public_key, "1234..5678".to_string());
88        assert_eq!(node.version, "".to_string());
89        assert_eq!(node.origin, None);
90        assert_eq!(node.docs, Docs::default());
91        assert_eq!(node.accounts, vec![]);
92        assert_eq!(node.instructions, vec![]);
93        assert_eq!(node.defined_types, vec![]);
94        assert_eq!(node.pdas, vec![]);
95        assert_eq!(node.errors, vec![]);
96    }
97
98    #[test]
99    fn default_program() {
100        let node = ProgramNode::default();
101        assert_eq!(node.name, CamelCaseString::new(""));
102        assert_eq!(node.public_key, "".to_string());
103        assert_eq!(node.version, "".to_string());
104        assert_eq!(node.origin, None);
105        assert_eq!(node.docs, Docs::default());
106        assert_eq!(node.accounts, vec![]);
107        assert_eq!(node.instructions, vec![]);
108        assert_eq!(node.defined_types, vec![]);
109        assert_eq!(node.pdas, vec![]);
110        assert_eq!(node.errors, vec![]);
111    }
112
113    #[test]
114    fn direct_instantiation() {
115        let node = ProgramNode {
116            name: "myProgram".into(),
117            public_key: "1234..5678".into(),
118            version: "1.2.3".into(),
119            ..ProgramNode::default()
120        };
121        assert_eq!(node.name, CamelCaseString::new("myProgram"));
122        assert_eq!(node.public_key, "1234..5678".to_string());
123        assert_eq!(node.version, "1.2.3".to_string());
124        assert_eq!(node.origin, None);
125        assert_eq!(node.docs, Docs::default());
126        assert_eq!(node.accounts, vec![]);
127        assert_eq!(node.instructions, vec![]);
128        assert_eq!(node.defined_types, vec![]);
129        assert_eq!(node.pdas, vec![]);
130        assert_eq!(node.errors, vec![]);
131    }
132
133    #[test]
134    fn to_json() {
135        let node = ProgramNode {
136            name: "myProgram".into(),
137            public_key: "1234..5678".into(),
138            version: "1.2.3".into(),
139            ..ProgramNode::default()
140        };
141        let json = serde_json::to_string(&node).unwrap();
142        assert_eq!(
143            json,
144            r#"{"kind":"programNode","name":"myProgram","publicKey":"1234..5678","version":"1.2.3","accounts":[],"instructions":[],"definedTypes":[],"pdas":[],"errors":[]}"#
145        );
146    }
147
148    #[test]
149    fn from_json() {
150        let json = r#"{"kind":"programNode","name":"myProgram","publicKey":"1234..5678","version":"1.2.3"}"#;
151        let node: ProgramNode = serde_json::from_str(json).unwrap();
152        assert_eq!(
153            node,
154            ProgramNode {
155                name: "myProgram".into(),
156                public_key: "1234..5678".into(),
157                version: "1.2.3".into(),
158                ..ProgramNode::default()
159            }
160        );
161    }
162}