codama_nodes/
program_node.rs

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