1use serde::Deserialize;
2use serde::Serialize;
3
4#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
5pub struct Idl {
6 #[serde(default, skip_serializing_if = "is_default")]
8 pub address: String,
9 #[serde(default, skip_serializing_if = "is_default")]
10 pub metadata: IdlMetadata,
11 #[serde(default, skip_serializing_if = "is_default")]
13 pub name: Option<String>,
14 #[serde(default, skip_serializing_if = "is_default")]
15 pub version: Option<String>,
16 #[serde(default, skip_serializing_if = "is_default")]
18 pub docs: Vec<String>,
19 pub instructions: Vec<IdlInstruction>,
20 #[serde(default, skip_serializing_if = "is_default")]
21 pub accounts: Vec<IdlAccount>,
22 #[serde(default, skip_serializing_if = "is_default")]
23 pub events: Vec<IdlEvent>,
24 #[serde(default, skip_serializing_if = "is_default")]
25 pub errors: Vec<IdlErrorCode>,
26 #[serde(default, skip_serializing_if = "is_default")]
27 pub types: Vec<IdlTypeDef>,
28 #[serde(default, skip_serializing_if = "is_default")]
29 pub constants: Vec<IdlConst>,
30}
31
32impl Idl {
33 pub fn get_name(&self) -> &str {
35 self.name.as_deref().unwrap_or(&self.metadata.name)
36 }
37
38 pub fn get_version(&self) -> &str {
40 self.version.as_deref().unwrap_or(&self.metadata.version)
41 }
42}
43
44#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
45pub struct IdlMetadata {
46 #[serde(default)]
47 pub name: String,
48 #[serde(default)]
49 pub version: String,
50 #[serde(default, skip_serializing_if = "is_default")]
51 pub spec: String,
52 #[serde(skip_serializing_if = "is_default")]
53 pub description: Option<String>,
54 #[serde(skip_serializing_if = "is_default")]
55 pub repository: Option<String>,
56 #[serde(default, skip_serializing_if = "is_default")]
57 pub dependencies: Vec<IdlDependency>,
58 #[serde(skip_serializing_if = "is_default")]
59 pub contact: Option<String>,
60 #[serde(skip_serializing_if = "is_default")]
61 pub deployments: Option<IdlDeployments>,
62}
63
64#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
65pub struct IdlDependency {
66 pub name: String,
67 pub version: String,
68}
69
70#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
71pub struct IdlDeployments {
72 pub mainnet: Option<String>,
73 pub testnet: Option<String>,
74 pub devnet: Option<String>,
75 pub localnet: Option<String>,
76}
77
78#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
79pub struct IdlInstruction {
80 pub name: String,
81 #[serde(default, skip_serializing_if = "is_default")]
82 pub docs: Vec<String>,
83 #[serde(default, skip_serializing_if = "is_default")]
84 pub discriminator: IdlDiscriminator,
85 pub accounts: Vec<IdlInstructionAccountItem>,
86 pub args: Vec<IdlField>,
87 #[serde(skip_serializing_if = "is_default")]
88 pub returns: Option<IdlType>,
89}
90
91#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
92#[serde(untagged)]
93pub enum IdlInstructionAccountItem {
94 Composite(IdlInstructionAccounts),
95 Single(IdlInstructionAccount),
96}
97
98#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
99pub struct IdlInstructionAccount {
100 pub name: String,
101 #[serde(default, skip_serializing_if = "is_default")]
102 pub docs: Vec<String>,
103 #[serde(default, skip_serializing_if = "is_default", alias = "isMut")]
104 pub writable: bool,
105 #[serde(default, skip_serializing_if = "is_default", alias = "isSigner")]
106 pub signer: bool,
107 #[serde(default, skip_serializing_if = "is_default")]
108 pub optional: bool,
109 #[serde(skip_serializing_if = "is_default")]
110 pub address: Option<String>,
111 #[serde(skip_serializing_if = "is_default")]
112 pub pda: Option<IdlPda>,
113 #[serde(default, skip_serializing_if = "is_default")]
114 pub relations: Vec<String>,
115}
116
117#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
118pub struct IdlInstructionAccounts {
119 pub name: String,
120 pub accounts: Vec<IdlInstructionAccountItem>,
121}
122
123#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
124pub struct IdlPda {
125 pub seeds: Vec<IdlSeed>,
126 #[serde(skip_serializing_if = "is_default")]
127 pub program: Option<IdlSeed>,
128}
129
130#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
131#[serde(tag = "kind", rename_all = "lowercase")]
132pub enum IdlSeed {
133 Const(IdlSeedConst),
134 Arg(IdlSeedArg),
135 Account(IdlSeedAccount),
136}
137
138#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
139pub struct IdlSeedConst {
140 pub value: Vec<u8>,
141}
142
143#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
144pub struct IdlSeedArg {
145 pub path: String,
146}
147
148#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
149pub struct IdlSeedAccount {
150 pub path: String,
151 #[serde(skip_serializing_if = "is_default")]
152 pub account: Option<String>,
153}
154
155#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
157pub struct IdlAccount {
158 pub name: String,
159 #[serde(default, skip_serializing_if = "is_default")]
160 pub discriminator: IdlDiscriminator,
161 #[serde(default, skip_serializing_if = "is_default", rename = "type")]
163 pub ty: Option<IdlTypeDefTy>,
164}
165
166#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
167pub struct IdlEvent {
168 pub name: String,
169 #[serde(default, skip_serializing_if = "is_default")]
170 pub discriminator: IdlDiscriminator,
171}
172
173#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
174pub struct IdlConst {
175 pub name: String,
176 #[serde(default, skip_serializing_if = "is_default")]
177 pub docs: Vec<String>,
178 #[serde(rename = "type")]
179 pub ty: IdlType,
180 pub value: String,
181}
182
183#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
184pub struct IdlErrorCode {
185 pub code: u32,
186 pub name: String,
187 #[serde(skip_serializing_if = "is_default")]
188 pub msg: Option<String>,
189}
190
191#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
192pub struct IdlField {
193 pub name: String,
194 #[serde(default, skip_serializing_if = "is_default")]
195 pub docs: Vec<String>,
196 #[serde(rename = "type")]
197 pub ty: IdlType,
198}
199
200#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
201pub struct IdlTypeDef {
202 pub name: String,
203 #[serde(default, skip_serializing_if = "is_default")]
204 pub docs: Vec<String>,
205 #[serde(default, skip_serializing_if = "is_default")]
206 pub serialization: IdlSerialization,
207 #[serde(skip_serializing_if = "is_default")]
208 pub repr: Option<IdlRepr>,
209 #[serde(default, skip_serializing_if = "is_default")]
210 pub generics: Vec<IdlTypeDefGeneric>,
211 #[serde(rename = "type")]
212 pub ty: IdlTypeDefTy,
213}
214
215#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
216#[serde(rename_all = "lowercase")]
217#[non_exhaustive]
218pub enum IdlSerialization {
219 #[default]
220 Borsh,
221 Bytemuck,
222 BytemuckUnsafe,
223 Custom(String),
224}
225
226#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
227#[serde(tag = "kind", rename_all = "lowercase")]
228#[non_exhaustive]
229pub enum IdlRepr {
230 Rust(IdlReprModifier),
231 C(IdlReprModifier),
232 Transparent,
233}
234
235#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
236pub struct IdlReprModifier {
237 #[serde(default, skip_serializing_if = "is_default")]
238 pub packed: bool,
239 #[serde(skip_serializing_if = "is_default")]
240 pub align: Option<usize>,
241}
242
243#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
245#[serde(untagged)]
246pub enum IdlTypeDefGeneric {
247 Simple(String),
249 Complex(IdlTypeDefGenericComplex),
251}
252
253impl IdlTypeDefGeneric {
254 pub fn get_name(&self) -> &str {
256 match self {
257 IdlTypeDefGeneric::Simple(name) => name,
258 IdlTypeDefGeneric::Complex(complex) => match complex {
259 IdlTypeDefGenericComplex::Type { name } => name,
260 IdlTypeDefGenericComplex::Const { name, .. } => name,
261 },
262 }
263 }
264}
265
266#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
267#[serde(tag = "kind", rename_all = "lowercase")]
268pub enum IdlTypeDefGenericComplex {
269 Type {
270 name: String,
271 },
272 Const {
273 name: String,
274 #[serde(rename = "type")]
275 ty: String,
276 },
277}
278
279#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
280#[serde(tag = "kind", rename_all = "lowercase")]
281pub enum IdlTypeDefTy {
282 Struct {
283 #[serde(skip_serializing_if = "is_default")]
284 fields: Option<IdlDefinedFields>,
285 },
286 Enum {
287 variants: Vec<IdlEnumVariant>,
288 },
289 Type {
290 alias: IdlType,
291 },
292}
293
294#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
295pub struct IdlEnumVariant {
296 pub name: String,
297 #[serde(skip_serializing_if = "is_default")]
298 pub fields: Option<IdlDefinedFields>,
299}
300
301#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
302#[serde(untagged)]
303pub enum IdlDefinedFields {
304 Named(Vec<IdlField>),
305 Tuple(Vec<IdlType>),
306}
307
308#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
309#[serde(rename_all = "lowercase")]
310pub enum IdlArrayLen {
311 Generic(String),
312 #[serde(untagged)]
313 Value(usize),
314}
315
316#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
318#[serde(untagged)]
319pub enum IdlGenericArg {
320 WithKind(IdlGenericArgWithKind),
322 Type {
324 #[serde(rename = "type")]
325 ty: IdlType,
326 },
327}
328
329#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
330#[serde(tag = "kind", rename_all = "lowercase")]
331pub enum IdlGenericArgWithKind {
332 Type {
333 #[serde(rename = "type")]
334 ty: IdlType,
335 },
336 Const {
337 value: String,
338 },
339}
340
341#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
342#[serde(rename_all = "camelCase")]
343pub enum IdlDefinedTypeArg {
344 Generic(String),
345 Value(String),
346 Type(IdlType),
347}
348
349#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
350#[serde(rename_all = "camelCase")]
351#[non_exhaustive]
352pub enum IdlType {
353 Bool,
354 U8,
355 I8,
356 U16,
357 I16,
358 U32,
359 I32,
360 F32,
361 U64,
362 I64,
363 F64,
364 U128,
365 I128,
366 U256,
367 I256,
368 Bytes,
369 String,
370 Pubkey,
372 PublicKey,
374 Option(Box<IdlType>),
375 Vec(Box<IdlType>),
376 Array(Box<IdlType>, IdlArrayLen),
377 Generic(String),
378 Defined(DefinedType),
380 DefinedWithTypeArgs(DefinedWithTypeArgs),
382}
383
384impl IdlType {
385 pub fn is_pubkey(&self) -> bool {
387 matches!(self, IdlType::Pubkey | IdlType::PublicKey)
388 }
389}
390
391#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
394#[serde(untagged)]
395pub enum DefinedType {
396 Simple(String),
398 Complex {
400 name: String,
401 #[serde(default, skip_serializing_if = "is_default")]
402 generics: Vec<IdlGenericArg>,
403 },
404}
405
406impl DefinedType {
407 pub fn get_name(&self) -> &str {
409 match self {
410 DefinedType::Simple(name) => name,
411 DefinedType::Complex { name, .. } => name,
412 }
413 }
414
415 pub fn get_generics(&self) -> &[IdlGenericArg] {
417 match self {
418 DefinedType::Simple(_) => &[],
419 DefinedType::Complex { generics, .. } => generics,
420 }
421 }
422}
423
424#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
426pub struct DefinedWithTypeArgs {
427 pub name: String,
428 #[serde(default, skip_serializing_if = "is_default")]
429 pub args: Vec<IdlGenericArg>,
430}
431
432pub type IdlDiscriminator = Vec<u8>;
433
434fn is_default<T: Default + PartialEq>(it: &T) -> bool {
436 *it == T::default()
437}