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