codama_nodes/
instruction_node.rs1use crate::{
2 CamelCaseString, DiscriminatorNode, Docs, InstructionAccountNode, InstructionArgumentNode,
3 InstructionByteDeltaNode, InstructionRemainingAccountsNode,
4};
5use codama_nodes_derive::node;
6use serde::{Deserialize, Serialize};
7
8#[node]
9#[derive(Default)]
10pub struct InstructionNode {
11 pub name: CamelCaseString,
13 #[serde(default, skip_serializing_if = "crate::is_default")]
14 pub docs: Docs,
15 #[serde(default, skip_serializing_if = "crate::is_default")]
16 pub optional_account_strategy: InstructionOptionalAccountStrategy,
17
18 pub accounts: Vec<InstructionAccountNode>,
20 pub arguments: Vec<InstructionArgumentNode>,
21 #[serde(default, skip_serializing_if = "crate::is_default")]
22 pub extra_arguments: Vec<InstructionArgumentNode>,
23 #[serde(default, skip_serializing_if = "crate::is_default")]
24 pub remaining_accounts: Vec<InstructionRemainingAccountsNode>,
25 #[serde(default, skip_serializing_if = "crate::is_default")]
26 pub byte_deltas: Vec<InstructionByteDeltaNode>,
27 #[serde(default, skip_serializing_if = "crate::is_default")]
28 pub discriminators: Vec<DiscriminatorNode>,
29 #[serde(default, skip_serializing_if = "crate::is_default")]
30 pub sub_instructions: Vec<InstructionNode>,
31}
32
33#[derive(Debug, PartialEq, Eq, Clone, Copy, Default, Serialize, Deserialize)]
34#[serde(rename_all = "camelCase")]
35pub enum InstructionOptionalAccountStrategy {
36 Omitted,
37 #[default]
38 ProgramId,
39}
40
41#[cfg(test)]
42mod tests {
43 use super::*;
44
45 #[test]
46 fn empty_instruction() {
47 let node = InstructionNode {
48 name: "myInstruction".into(),
49 ..InstructionNode::default()
50 };
51 assert_eq!(node.name, CamelCaseString::new("myInstruction"));
52 assert_eq!(node.docs, Docs::default());
53 assert_eq!(
54 node.optional_account_strategy,
55 InstructionOptionalAccountStrategy::ProgramId
56 );
57 assert_eq!(node.accounts, vec![]);
58 assert_eq!(node.arguments, vec![]);
59 assert_eq!(node.extra_arguments, vec![]);
60 assert_eq!(node.remaining_accounts, vec![]);
61 assert_eq!(node.byte_deltas, vec![]);
62 assert_eq!(node.discriminators, vec![]);
63 assert_eq!(node.sub_instructions, vec![]);
64 }
65
66 #[test]
67 fn instruction_with_sub_instructions() {
68 let node = InstructionNode {
69 name: "myInstruction".into(),
70 sub_instructions: vec![
71 InstructionNode {
72 name: "mySubInstructionA".into(),
73 ..InstructionNode::default()
74 },
75 InstructionNode {
76 name: "mySubInstructionB".into(),
77 ..InstructionNode::default()
78 },
79 ],
80 ..InstructionNode::default()
81 };
82 assert_eq!(
83 node.sub_instructions,
84 vec![
85 InstructionNode {
86 name: "mySubInstructionA".into(),
87 ..InstructionNode::default()
88 },
89 InstructionNode {
90 name: "mySubInstructionB".into(),
91 ..InstructionNode::default()
92 },
93 ]
94 );
95 }
96
97 #[test]
98 fn to_json() {
99 let node = InstructionNode {
100 name: "myInstruction".into(),
101 ..InstructionNode::default()
102 };
103 let json = serde_json::to_string(&node).unwrap();
104 assert_eq!(
105 json,
106 r#"{"kind":"instructionNode","name":"myInstruction","accounts":[],"arguments":[]}"#
107 );
108 }
109
110 #[test]
111 fn from_json() {
112 let json =
113 r#"{"kind":"instructionNode","name":"myInstruction","accounts":[],"arguments":[]}"#;
114 let node: InstructionNode = serde_json::from_str(json).unwrap();
115 assert_eq!(
116 node,
117 InstructionNode {
118 name: "myInstruction".into(),
119 ..InstructionNode::default()
120 }
121 );
122 }
123}