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