1#![cfg_attr(docsrs, feature(doc_auto_cfg))]
2
3pub mod codegen;
4pub mod parser;
5
6#[cfg(feature = "idl-build")]
7pub mod idl;
8
9#[cfg(feature = "hash")]
10pub mod hash;
11#[cfg(not(feature = "hash"))]
12pub(crate) mod hash;
13
14use codegen::accounts as accounts_codegen;
15use codegen::program as program_codegen;
16use parser::accounts as accounts_parser;
17use parser::program as program_parser;
18use proc_macro2::{Span, TokenStream};
19use quote::quote;
20use quote::ToTokens;
21use std::collections::HashMap;
22use std::ops::Deref;
23use syn::ext::IdentExt;
24use syn::parse::{Error as ParseError, Parse, ParseStream, Result as ParseResult};
25use syn::punctuated::Punctuated;
26use syn::spanned::Spanned;
27use syn::token::Comma;
28use syn::Attribute;
29use syn::Lit;
30use syn::{
31 Expr, Generics, Ident, ItemEnum, ItemFn, ItemMod, ItemStruct, LitInt, PatType, Token, Type,
32 TypePath,
33};
34
35#[derive(Debug)]
36pub struct Program {
37 pub ixs: Vec<Ix>,
38 pub name: Ident,
39 pub docs: Option<Vec<String>>,
40 pub program_mod: ItemMod,
41 pub fallback_fn: Option<FallbackFn>,
42}
43
44impl Parse for Program {
45 fn parse(input: ParseStream) -> ParseResult<Self> {
46 let program_mod = <ItemMod as Parse>::parse(input)?;
47 program_parser::parse(program_mod)
48 }
49}
50
51impl From<&Program> for TokenStream {
52 fn from(program: &Program) -> Self {
53 program_codegen::generate(program)
54 }
55}
56
57impl ToTokens for Program {
58 fn to_tokens(&self, tokens: &mut TokenStream) {
59 tokens.extend::<TokenStream>(self.into());
60 }
61}
62
63#[derive(Debug)]
64pub struct Ix {
65 pub raw_method: ItemFn,
66 pub ident: Ident,
67 pub docs: Option<Vec<String>>,
68 pub cfgs: Vec<Attribute>,
69 pub args: Vec<IxArg>,
70 pub returns: IxReturn,
71 pub anchor_ident: Ident,
73 pub interface_discriminator: Option<[u8; 8]>,
76 pub overrides: Option<Overrides>,
78}
79
80#[derive(Debug, Default)]
82pub struct Overrides {
83 pub discriminator: Option<TokenStream>,
85}
86
87impl Parse for Overrides {
88 fn parse(input: ParseStream) -> ParseResult<Self> {
89 let mut attr = Self::default();
90 let args = input.parse_terminated::<_, Comma>(NamedArg::parse)?;
91 for arg in args {
92 match arg.name.to_string().as_str() {
93 "discriminator" => {
94 let value = match &arg.value {
95 Expr::Lit(lit) if matches!(lit.lit, Lit::Int(_)) => quote! { &[#lit] },
97 Expr::Array(arr) => quote! { &#arr },
99 expr => expr.to_token_stream(),
100 };
101 attr.discriminator.replace(value)
102 }
103 _ => return Err(ParseError::new(arg.name.span(), "Invalid argument")),
104 };
105 }
106
107 Ok(attr)
108 }
109}
110
111struct NamedArg {
112 name: Ident,
113 #[allow(dead_code)]
114 eq_token: Token![=],
115 value: Expr,
116}
117
118impl Parse for NamedArg {
119 fn parse(input: ParseStream) -> ParseResult<Self> {
120 Ok(Self {
121 name: input.parse()?,
122 eq_token: input.parse()?,
123 value: input.parse()?,
124 })
125 }
126}
127
128#[derive(Debug)]
129pub struct IxArg {
130 pub name: Ident,
131 pub docs: Option<Vec<String>>,
132 pub raw_arg: PatType,
133}
134
135#[derive(Debug)]
136pub struct IxReturn {
137 pub ty: Type,
138}
139
140#[derive(Debug)]
141pub struct FallbackFn {
142 raw_method: ItemFn,
143}
144
145#[derive(Debug)]
146pub struct AccountsStruct {
147 pub ident: Ident,
149 pub generics: Generics,
151 pub fields: Vec<AccountField>,
153 instruction_api: Option<Punctuated<Expr, Comma>>,
155}
156
157impl Parse for AccountsStruct {
158 fn parse(input: ParseStream) -> ParseResult<Self> {
159 let strct = <ItemStruct as Parse>::parse(input)?;
160 accounts_parser::parse(&strct)
161 }
162}
163
164impl From<&AccountsStruct> for TokenStream {
165 fn from(accounts: &AccountsStruct) -> Self {
166 accounts_codegen::generate(accounts)
167 }
168}
169
170impl ToTokens for AccountsStruct {
171 fn to_tokens(&self, tokens: &mut TokenStream) {
172 tokens.extend::<TokenStream>(self.into());
173 }
174}
175
176impl AccountsStruct {
177 pub fn new(
178 strct: ItemStruct,
179 fields: Vec<AccountField>,
180 instruction_api: Option<Punctuated<Expr, Comma>>,
181 ) -> Self {
182 let ident = strct.ident.clone();
183 let generics = strct.generics;
184 Self {
185 ident,
186 generics,
187 fields,
188 instruction_api,
189 }
190 }
191
192 pub fn instruction_args(&self) -> Option<HashMap<String, String>> {
196 self.instruction_api.as_ref().map(|instruction_api| {
197 instruction_api
198 .iter()
199 .map(|expr| {
200 let arg = parser::tts_to_string(expr);
201 let components: Vec<&str> = arg.split(" : ").collect();
202 assert!(components.len() == 2);
203 (components[0].to_string(), components[1].to_string())
204 })
205 .collect()
206 })
207 }
208
209 pub fn field_names(&self) -> Vec<String> {
210 self.fields
211 .iter()
212 .map(|field| field.ident().to_string())
213 .collect()
214 }
215
216 pub fn has_optional(&self) -> bool {
217 for field in &self.fields {
218 if let AccountField::Field(field) = field {
219 if field.is_optional {
220 return true;
221 }
222 }
223 }
224 false
225 }
226
227 pub fn is_field_optional<T: quote::ToTokens>(&self, field: &T) -> bool {
228 let matching_field = self
229 .fields
230 .iter()
231 .find(|f| *f.ident() == parser::tts_to_string(field));
232 if let Some(matching_field) = matching_field {
233 matching_field.is_optional()
234 } else {
235 false
236 }
237 }
238}
239
240#[allow(clippy::large_enum_variant)]
241#[derive(Debug)]
242pub enum AccountField {
243 Field(Field),
244 CompositeField(CompositeField),
245}
246
247impl AccountField {
248 fn ident(&self) -> &Ident {
249 match self {
250 AccountField::Field(field) => &field.ident,
251 AccountField::CompositeField(c_field) => &c_field.ident,
252 }
253 }
254
255 fn is_optional(&self) -> bool {
256 match self {
257 AccountField::Field(field) => field.is_optional,
258 AccountField::CompositeField(_) => false,
259 }
260 }
261
262 pub fn ty_name(&self) -> Option<String> {
263 let qualified_ty_name = match self {
264 AccountField::Field(field) => match &field.ty {
265 Ty::Account(account) => Some(parser::tts_to_string(&account.account_type_path)),
266 Ty::LazyAccount(account) => Some(parser::tts_to_string(&account.account_type_path)),
267 _ => None,
268 },
269 AccountField::CompositeField(field) => Some(field.symbol.clone()),
270 };
271
272 qualified_ty_name.map(|name| match name.rsplit_once(" :: ") {
273 Some((_prefix, suffix)) => suffix.to_string(),
274 None => name,
275 })
276 }
277}
278
279#[derive(Debug)]
280pub struct Field {
281 pub ident: Ident,
282 pub constraints: ConstraintGroup,
283 pub ty: Ty,
284 pub is_optional: bool,
285 pub docs: Option<Vec<String>>,
287}
288
289impl Field {
290 pub fn typed_ident(&self) -> proc_macro2::TokenStream {
291 let name = &self.ident;
292 let ty_decl = self.ty_decl(false);
293 quote! {
294 #name: #ty_decl
295 }
296 }
297
298 pub fn ty_decl(&self, ignore_option: bool) -> proc_macro2::TokenStream {
299 let account_ty = self.account_ty();
300 let container_ty = self.container_ty();
301 let inner_ty = match &self.ty {
302 Ty::AccountInfo => quote! {
303 AccountInfo
304 },
305 Ty::UncheckedAccount => quote! {
306 UncheckedAccount
307 },
308 Ty::Signer => quote! {
309 Signer
310 },
311 Ty::ProgramData => quote! {
312 ProgramData
313 },
314 Ty::SystemAccount => quote! {
315 SystemAccount
316 },
317 Ty::Account(AccountTy { boxed, .. })
318 | Ty::InterfaceAccount(InterfaceAccountTy { boxed, .. }) => {
319 if *boxed {
320 quote! {
321 Box<#container_ty<#account_ty>>
322 }
323 } else {
324 quote! {
325 #container_ty<#account_ty>
326 }
327 }
328 }
329 Ty::Sysvar(ty) => {
330 let account = match ty {
331 SysvarTy::Clock => quote! {Clock},
332 SysvarTy::Rent => quote! {Rent},
333 SysvarTy::EpochSchedule => quote! {EpochSchedule},
334 SysvarTy::Fees => quote! {Fees},
335 SysvarTy::RecentBlockhashes => quote! {RecentBlockhashes},
336 SysvarTy::SlotHashes => quote! {SlotHashes},
337 SysvarTy::SlotHistory => quote! {SlotHistory},
338 SysvarTy::StakeHistory => quote! {StakeHistory},
339 SysvarTy::Instructions => quote! {Instructions},
340 SysvarTy::Rewards => quote! {Rewards},
341 };
342 quote! {
343 Sysvar<#account>
344 }
345 }
346 _ => quote! {
347 #container_ty<#account_ty>
348 },
349 };
350 if self.is_optional && !ignore_option {
351 quote! {
352 Option<#inner_ty>
353 }
354 } else {
355 quote! {
356 #inner_ty
357 }
358 }
359 }
360
361 pub fn from_account_info(
364 &self,
365 kind: Option<&InitKind>,
366 checked: bool,
367 ) -> proc_macro2::TokenStream {
368 let field = &self.ident;
369 let field_str = field.to_string();
370 let container_ty = self.container_ty();
371 let owner_addr = match &kind {
372 None => quote! { __program_id },
373 Some(InitKind::Program { .. }) => quote! {
374 __program_id
375 },
376 _ => quote! {
377 &anchor_spl::token::ID
378 },
379 };
380 match &self.ty {
381 Ty::AccountInfo => quote! { #field.to_account_info() },
382 Ty::UncheckedAccount => {
383 quote! { UncheckedAccount::try_from(&#field) }
384 }
385 Ty::Account(AccountTy { boxed, .. })
386 | Ty::InterfaceAccount(InterfaceAccountTy { boxed, .. }) => {
387 let stream = if checked {
388 quote! {
389 match #container_ty::try_from(&#field) {
390 Ok(val) => val,
391 Err(e) => return Err(e.with_account_name(#field_str))
392 }
393 }
394 } else {
395 quote! {
396 match #container_ty::try_from_unchecked(&#field) {
397 Ok(val) => val,
398 Err(e) => return Err(e.with_account_name(#field_str))
399 }
400 }
401 };
402 if *boxed {
403 quote! {
404 Box::new(#stream)
405 }
406 } else {
407 stream
408 }
409 }
410 Ty::LazyAccount(_) => {
411 if checked {
412 quote! {
413 match #container_ty::try_from(&#field) {
414 Ok(val) => val,
415 Err(e) => return Err(e.with_account_name(#field_str))
416 }
417 }
418 } else {
419 quote! {
420 match #container_ty::try_from_unchecked(&#field) {
421 Ok(val) => val,
422 Err(e) => return Err(e.with_account_name(#field_str))
423 }
424 }
425 }
426 }
427 Ty::AccountLoader(_) => {
428 if checked {
429 quote! {
430 match #container_ty::try_from(&#field) {
431 Ok(val) => val,
432 Err(e) => return Err(e.with_account_name(#field_str))
433 }
434 }
435 } else {
436 quote! {
437 match #container_ty::try_from_unchecked(#owner_addr, &#field) {
438 Ok(val) => val,
439 Err(e) => return Err(e.with_account_name(#field_str))
440 }
441 }
442 }
443 }
444 _ => {
445 if checked {
446 quote! {
447 match #container_ty::try_from(#owner_addr, &#field) {
448 Ok(val) => val,
449 Err(e) => return Err(e.with_account_name(#field_str))
450 }
451 }
452 } else {
453 quote! {
454 match #container_ty::try_from_unchecked(#owner_addr, &#field) {
455 Ok(val) => val,
456 Err(e) => return Err(e.with_account_name(#field_str))
457 }
458 }
459 }
460 }
461 }
462 }
463
464 pub fn container_ty(&self) -> proc_macro2::TokenStream {
465 match &self.ty {
466 Ty::Account(_) => quote! {
467 anchor_lang::accounts::account::Account
468 },
469 Ty::LazyAccount(_) => quote! {
470 anchor_lang::accounts::lazy_account::LazyAccount
471 },
472 Ty::AccountLoader(_) => quote! {
473 anchor_lang::accounts::account_loader::AccountLoader
474 },
475 Ty::Sysvar(_) => quote! { anchor_lang::accounts::sysvar::Sysvar },
476 Ty::Program(_) => quote! { anchor_lang::accounts::program::Program },
477 Ty::Interface(_) => quote! { anchor_lang::accounts::interface::Interface },
478 Ty::InterfaceAccount(_) => {
479 quote! { anchor_lang::accounts::interface_account::InterfaceAccount }
480 }
481 Ty::AccountInfo => quote! {},
482 Ty::UncheckedAccount => quote! {},
483 Ty::Signer => quote! {},
484 Ty::SystemAccount => quote! {},
485 Ty::ProgramData => quote! {},
486 }
487 }
488
489 pub fn account_ty(&self) -> proc_macro2::TokenStream {
491 match &self.ty {
492 Ty::AccountInfo => quote! {
493 AccountInfo
494 },
495 Ty::UncheckedAccount => quote! {
496 UncheckedAccount
497 },
498 Ty::Signer => quote! {
499 Signer
500 },
501 Ty::SystemAccount => quote! {
502 SystemAccount
503 },
504 Ty::ProgramData => quote! {
505 ProgramData
506 },
507 Ty::Account(ty) => {
508 let ident = &ty.account_type_path;
509 quote! {
510 #ident
511 }
512 }
513 Ty::LazyAccount(ty) => {
514 let ident = &ty.account_type_path;
515 quote! {
516 #ident
517 }
518 }
519 Ty::InterfaceAccount(ty) => {
520 let ident = &ty.account_type_path;
521 quote! {
522 #ident
523 }
524 }
525 Ty::AccountLoader(ty) => {
526 let ident = &ty.account_type_path;
527 quote! {
528 #ident
529 }
530 }
531 Ty::Sysvar(ty) => match ty {
532 SysvarTy::Clock => quote! {Clock},
533 SysvarTy::Rent => quote! {Rent},
534 SysvarTy::EpochSchedule => quote! {EpochSchedule},
535 SysvarTy::Fees => quote! {Fees},
536 SysvarTy::RecentBlockhashes => quote! {RecentBlockhashes},
537 SysvarTy::SlotHashes => quote! {SlotHashes},
538 SysvarTy::SlotHistory => quote! {SlotHistory},
539 SysvarTy::StakeHistory => quote! {StakeHistory},
540 SysvarTy::Instructions => quote! {Instructions},
541 SysvarTy::Rewards => quote! {Rewards},
542 },
543 Ty::Program(ty) => {
544 let program = &ty.account_type_path;
545 quote! {
546 #program
547 }
548 }
549 Ty::Interface(ty) => {
550 let program = &ty.account_type_path;
551 quote! {
552 #program
553 }
554 }
555 }
556 }
557}
558
559#[derive(Debug)]
560pub struct CompositeField {
561 pub ident: Ident,
562 pub constraints: ConstraintGroup,
563 pub symbol: String,
564 pub raw_field: syn::Field,
565 pub docs: Option<Vec<String>>,
567}
568
569#[derive(Debug, PartialEq, Eq)]
571pub enum Ty {
572 AccountInfo,
573 UncheckedAccount,
574 AccountLoader(AccountLoaderTy),
575 Sysvar(SysvarTy),
576 Account(AccountTy),
577 LazyAccount(LazyAccountTy),
578 Program(ProgramTy),
579 Interface(InterfaceTy),
580 InterfaceAccount(InterfaceAccountTy),
581 Signer,
582 SystemAccount,
583 ProgramData,
584}
585
586#[derive(Debug, PartialEq, Eq)]
587pub enum SysvarTy {
588 Clock,
589 Rent,
590 EpochSchedule,
591 Fees,
592 RecentBlockhashes,
593 SlotHashes,
594 SlotHistory,
595 StakeHistory,
596 Instructions,
597 Rewards,
598}
599
600#[derive(Debug, PartialEq, Eq)]
601pub struct AccountLoaderTy {
602 pub account_type_path: TypePath,
604}
605
606#[derive(Debug, PartialEq, Eq)]
607pub struct AccountTy {
608 pub account_type_path: TypePath,
610 pub boxed: bool,
612}
613
614#[derive(Debug, PartialEq, Eq)]
615pub struct LazyAccountTy {
616 pub account_type_path: TypePath,
618}
619
620#[derive(Debug, PartialEq, Eq)]
621pub struct InterfaceAccountTy {
622 pub account_type_path: TypePath,
624 pub boxed: bool,
626}
627
628#[derive(Debug, PartialEq, Eq)]
629pub struct ProgramTy {
630 pub account_type_path: TypePath,
632}
633
634#[derive(Debug, PartialEq, Eq)]
635pub struct InterfaceTy {
636 pub account_type_path: TypePath,
638}
639
640#[derive(Debug)]
641pub struct Error {
642 pub name: String,
643 pub raw_enum: ItemEnum,
644 pub ident: Ident,
645 pub codes: Vec<ErrorCode>,
646 pub args: Option<ErrorArgs>,
647}
648
649#[derive(Debug)]
650pub struct ErrorArgs {
651 pub offset: LitInt,
652}
653
654impl Parse for ErrorArgs {
655 fn parse(stream: ParseStream) -> ParseResult<Self> {
656 let offset_span = stream.span();
657 let offset = stream.call(Ident::parse_any)?;
658 if offset.to_string().as_str() != "offset" {
659 return Err(ParseError::new(offset_span, "expected keyword offset"));
660 }
661 stream.parse::<Token![=]>()?;
662 Ok(ErrorArgs {
663 offset: stream.parse()?,
664 })
665 }
666}
667
668#[derive(Debug)]
669pub struct ErrorCode {
670 pub id: u32,
671 pub ident: Ident,
672 pub msg: Option<String>,
673}
674
675#[derive(Debug, Default, Clone)]
677pub struct ConstraintGroup {
678 pub init: Option<ConstraintInitGroup>,
679 pub zeroed: Option<ConstraintZeroed>,
680 pub mutable: Option<ConstraintMut>,
681 pub signer: Option<ConstraintSigner>,
682 pub owner: Option<ConstraintOwner>,
683 pub rent_exempt: Option<ConstraintRentExempt>,
684 pub seeds: Option<ConstraintSeedsGroup>,
685 pub executable: Option<ConstraintExecutable>,
686 pub has_one: Vec<ConstraintHasOne>,
687 pub raw: Vec<ConstraintRaw>,
688 pub close: Option<ConstraintClose>,
689 pub address: Option<ConstraintAddress>,
690 pub associated_token: Option<ConstraintAssociatedToken>,
691 pub token_account: Option<ConstraintTokenAccountGroup>,
692 pub mint: Option<ConstraintTokenMintGroup>,
693 pub realloc: Option<ConstraintReallocGroup>,
694}
695
696impl ConstraintGroup {
697 pub fn is_zeroed(&self) -> bool {
698 self.zeroed.is_some()
699 }
700
701 pub fn is_mutable(&self) -> bool {
702 self.mutable.is_some()
703 }
704
705 pub fn is_signer(&self) -> bool {
706 self.signer.is_some()
707 }
708
709 pub fn is_close(&self) -> bool {
710 self.close.is_some()
711 }
712}
713
714#[allow(clippy::large_enum_variant)]
718#[derive(Debug)]
719pub enum Constraint {
720 Init(ConstraintInitGroup),
721 Zeroed(ConstraintZeroed),
722 Mut(ConstraintMut),
723 Signer(ConstraintSigner),
724 HasOne(ConstraintHasOne),
725 Raw(ConstraintRaw),
726 Owner(ConstraintOwner),
727 RentExempt(ConstraintRentExempt),
728 Seeds(ConstraintSeedsGroup),
729 AssociatedToken(ConstraintAssociatedToken),
730 Executable(ConstraintExecutable),
731 Close(ConstraintClose),
732 Address(ConstraintAddress),
733 TokenAccount(ConstraintTokenAccountGroup),
734 Mint(ConstraintTokenMintGroup),
735 Realloc(ConstraintReallocGroup),
736}
737
738#[allow(clippy::large_enum_variant)]
740#[derive(Debug)]
741pub enum ConstraintToken {
742 Init(Context<ConstraintInit>),
743 Zeroed(Context<ConstraintZeroed>),
744 Mut(Context<ConstraintMut>),
745 Signer(Context<ConstraintSigner>),
746 HasOne(Context<ConstraintHasOne>),
747 Raw(Context<ConstraintRaw>),
748 Owner(Context<ConstraintOwner>),
749 RentExempt(Context<ConstraintRentExempt>),
750 Seeds(Context<ConstraintSeeds>),
751 Executable(Context<ConstraintExecutable>),
752 Close(Context<ConstraintClose>),
753 Payer(Context<ConstraintPayer>),
754 Space(Context<ConstraintSpace>),
755 Address(Context<ConstraintAddress>),
756 TokenMint(Context<ConstraintTokenMint>),
757 TokenAuthority(Context<ConstraintTokenAuthority>),
758 TokenTokenProgram(Context<ConstraintTokenProgram>),
759 AssociatedTokenMint(Context<ConstraintTokenMint>),
760 AssociatedTokenAuthority(Context<ConstraintTokenAuthority>),
761 AssociatedTokenTokenProgram(Context<ConstraintTokenProgram>),
762 MintAuthority(Context<ConstraintMintAuthority>),
763 MintFreezeAuthority(Context<ConstraintMintFreezeAuthority>),
764 MintDecimals(Context<ConstraintMintDecimals>),
765 MintTokenProgram(Context<ConstraintTokenProgram>),
766 Bump(Context<ConstraintTokenBump>),
767 ProgramSeed(Context<ConstraintProgramSeed>),
768 Realloc(Context<ConstraintRealloc>),
769 ReallocPayer(Context<ConstraintReallocPayer>),
770 ReallocZero(Context<ConstraintReallocZero>),
771 ExtensionGroupPointerAuthority(Context<ConstraintExtensionAuthority>),
773 ExtensionGroupPointerGroupAddress(Context<ConstraintExtensionGroupPointerGroupAddress>),
774 ExtensionGroupMemberPointerAuthority(Context<ConstraintExtensionAuthority>),
775 ExtensionGroupMemberPointerMemberAddress(
776 Context<ConstraintExtensionGroupMemberPointerMemberAddress>,
777 ),
778 ExtensionMetadataPointerAuthority(Context<ConstraintExtensionAuthority>),
779 ExtensionMetadataPointerMetadataAddress(
780 Context<ConstraintExtensionMetadataPointerMetadataAddress>,
781 ),
782 ExtensionCloseAuthority(Context<ConstraintExtensionAuthority>),
783 ExtensionTokenHookAuthority(Context<ConstraintExtensionAuthority>),
784 ExtensionTokenHookProgramId(Context<ConstraintExtensionTokenHookProgramId>),
785 ExtensionPermanentDelegate(Context<ConstraintExtensionPermanentDelegate>),
786}
787
788impl Parse for ConstraintToken {
789 fn parse(stream: ParseStream) -> ParseResult<Self> {
790 accounts_parser::constraints::parse_token(stream)
791 }
792}
793
794#[derive(Debug, Clone)]
795pub struct ConstraintInit {
796 pub if_needed: bool,
797}
798
799#[derive(Debug, Clone)]
800pub struct ConstraintInitIfNeeded {}
801
802#[derive(Debug, Clone)]
803pub struct ConstraintZeroed {}
804
805#[derive(Debug, Clone)]
806pub struct ConstraintMut {
807 pub error: Option<Expr>,
808}
809
810#[derive(Debug, Clone)]
811pub struct ConstraintReallocGroup {
812 pub payer: Expr,
813 pub space: Expr,
814 pub zero: Expr,
815}
816
817#[derive(Debug, Clone)]
818pub struct ConstraintRealloc {
819 pub space: Expr,
820}
821
822#[derive(Debug, Clone)]
823pub struct ConstraintReallocPayer {
824 pub target: Expr,
825}
826
827#[derive(Debug, Clone)]
828pub struct ConstraintReallocZero {
829 pub zero: Expr,
830}
831
832#[derive(Debug, Clone)]
833pub struct ConstraintSigner {
834 pub error: Option<Expr>,
835}
836
837#[derive(Debug, Clone)]
838pub struct ConstraintHasOne {
839 pub join_target: Expr,
840 pub error: Option<Expr>,
841}
842
843#[derive(Debug, Clone)]
844pub struct ConstraintRaw {
845 pub raw: Expr,
846 pub error: Option<Expr>,
847}
848
849#[derive(Debug, Clone)]
850pub struct ConstraintOwner {
851 pub owner_address: Expr,
852 pub error: Option<Expr>,
853}
854
855#[derive(Debug, Clone)]
856pub struct ConstraintAddress {
857 pub address: Expr,
858 pub error: Option<Expr>,
859}
860
861#[derive(Debug, Clone)]
862pub enum ConstraintRentExempt {
863 Enforce,
864 Skip,
865}
866
867#[derive(Debug, Clone)]
868pub struct ConstraintInitGroup {
869 pub if_needed: bool,
870 pub seeds: Option<ConstraintSeedsGroup>,
871 pub payer: Expr,
872 pub space: Option<Expr>,
873 pub kind: InitKind,
874}
875
876#[derive(Debug, Clone)]
877pub struct ConstraintSeedsGroup {
878 pub is_init: bool,
879 pub seeds: Punctuated<Expr, Token![,]>,
880 pub bump: Option<Expr>, pub program_seed: Option<Expr>, }
883
884#[derive(Debug, Clone)]
885pub struct ConstraintSeeds {
886 pub seeds: Punctuated<Expr, Token![,]>,
887}
888
889#[derive(Debug, Clone)]
890pub struct ConstraintExecutable {}
891
892#[derive(Debug, Clone)]
893pub struct ConstraintPayer {
894 pub target: Expr,
895}
896
897#[derive(Debug, Clone)]
898pub struct ConstraintSpace {
899 pub space: Expr,
900}
901
902#[derive(Debug, Clone)]
904pub struct ConstraintExtensionAuthority {
905 pub authority: Expr,
906}
907
908#[derive(Debug, Clone)]
909pub struct ConstraintExtensionGroupPointerGroupAddress {
910 pub group_address: Expr,
911}
912
913#[derive(Debug, Clone)]
914pub struct ConstraintExtensionGroupMemberPointerMemberAddress {
915 pub member_address: Expr,
916}
917
918#[derive(Debug, Clone)]
919pub struct ConstraintExtensionMetadataPointerMetadataAddress {
920 pub metadata_address: Expr,
921}
922
923#[derive(Debug, Clone)]
924pub struct ConstraintExtensionTokenHookProgramId {
925 pub program_id: Expr,
926}
927
928#[derive(Debug, Clone)]
929pub struct ConstraintExtensionPermanentDelegate {
930 pub permanent_delegate: Expr,
931}
932
933#[derive(Debug, Clone)]
934#[allow(clippy::large_enum_variant)]
935pub enum InitKind {
936 Program {
937 owner: Option<Expr>,
938 },
939 Interface {
940 owner: Option<Expr>,
941 },
942 Token {
945 owner: Expr,
946 mint: Expr,
947 token_program: Option<Expr>,
948 },
949 AssociatedToken {
950 owner: Expr,
951 mint: Expr,
952 token_program: Option<Expr>,
953 },
954 Mint {
955 owner: Expr,
956 freeze_authority: Option<Expr>,
957 decimals: Expr,
958 token_program: Option<Expr>,
959 group_pointer_authority: Option<Expr>,
961 group_pointer_group_address: Option<Expr>,
962 group_member_pointer_authority: Option<Expr>,
963 group_member_pointer_member_address: Option<Expr>,
964 metadata_pointer_authority: Option<Expr>,
965 metadata_pointer_metadata_address: Option<Expr>,
966 close_authority: Option<Expr>,
967 permanent_delegate: Option<Expr>,
968 transfer_hook_authority: Option<Expr>,
969 transfer_hook_program_id: Option<Expr>,
970 },
971}
972
973#[derive(Debug, Clone)]
974pub struct ConstraintClose {
975 pub sol_dest: Ident,
976}
977
978#[derive(Debug, Clone)]
979pub struct ConstraintTokenMint {
980 pub mint: Expr,
981}
982
983#[derive(Debug, Clone)]
984pub struct ConstraintMintConfidentialTransferData {
985 pub confidential_transfer_data: Expr,
986}
987
988#[derive(Debug, Clone)]
989pub struct ConstraintMintMetadata {
990 pub token_metadata: Expr,
991}
992
993#[derive(Debug, Clone)]
994pub struct ConstraintMintTokenGroupData {
995 pub token_group_data: Expr,
996}
997
998#[derive(Debug, Clone)]
999pub struct ConstraintMintTokenGroupMemberData {
1000 pub token_group_member_data: Expr,
1001}
1002
1003#[derive(Debug, Clone)]
1004pub struct ConstraintMintMetadataPointerData {
1005 pub metadata_pointer_data: Expr,
1006}
1007
1008#[derive(Debug, Clone)]
1009pub struct ConstraintMintGroupPointerData {
1010 pub group_pointer_data: Expr,
1011}
1012
1013#[derive(Debug, Clone)]
1014pub struct ConstraintMintGroupMemberPointerData {
1015 pub group_member_pointer_data: Expr,
1016}
1017
1018#[derive(Debug, Clone)]
1019pub struct ConstraintMintCloseAuthority {
1020 pub close_authority: Expr,
1021}
1022
1023#[derive(Debug, Clone)]
1024pub struct ConstraintTokenAuthority {
1025 pub auth: Expr,
1026}
1027
1028#[derive(Debug, Clone)]
1029pub struct ConstraintTokenProgram {
1030 token_program: Expr,
1031}
1032
1033#[derive(Debug, Clone)]
1034pub struct ConstraintMintAuthority {
1035 pub mint_auth: Expr,
1036}
1037
1038#[derive(Debug, Clone)]
1039pub struct ConstraintMintFreezeAuthority {
1040 pub mint_freeze_auth: Expr,
1041}
1042
1043#[derive(Debug, Clone)]
1044pub struct ConstraintMintDecimals {
1045 pub decimals: Expr,
1046}
1047
1048#[derive(Debug, Clone)]
1049pub struct ConstraintTokenBump {
1050 pub bump: Option<Expr>,
1051}
1052
1053#[derive(Debug, Clone)]
1054pub struct ConstraintProgramSeed {
1055 pub program_seed: Expr,
1056}
1057
1058#[derive(Debug, Clone)]
1059pub struct ConstraintAssociatedToken {
1060 pub wallet: Expr,
1061 pub mint: Expr,
1062 pub token_program: Option<Expr>,
1063}
1064
1065#[derive(Debug, Clone)]
1066pub struct ConstraintTokenAccountGroup {
1067 pub mint: Option<Expr>,
1068 pub authority: Option<Expr>,
1069 pub token_program: Option<Expr>,
1070}
1071
1072#[derive(Debug, Clone)]
1073pub struct ConstraintTokenMintGroup {
1074 pub decimals: Option<Expr>,
1075 pub mint_authority: Option<Expr>,
1076 pub freeze_authority: Option<Expr>,
1077 pub token_program: Option<Expr>,
1078 pub group_pointer_authority: Option<Expr>,
1079 pub group_pointer_group_address: Option<Expr>,
1080 pub group_member_pointer_authority: Option<Expr>,
1081 pub group_member_pointer_member_address: Option<Expr>,
1082 pub metadata_pointer_authority: Option<Expr>,
1083 pub metadata_pointer_metadata_address: Option<Expr>,
1084 pub close_authority: Option<Expr>,
1085 pub permanent_delegate: Option<Expr>,
1086 pub transfer_hook_authority: Option<Expr>,
1087 pub transfer_hook_program_id: Option<Expr>,
1088}
1089
1090#[derive(Debug, Clone)]
1092pub struct Context<T> {
1093 span: Span,
1094 inner: T,
1095}
1096
1097impl<T> Context<T> {
1098 pub fn new(span: Span, inner: T) -> Self {
1099 Self { span, inner }
1100 }
1101
1102 pub fn into_inner(self) -> T {
1103 self.inner
1104 }
1105}
1106
1107impl<T> Deref for Context<T> {
1108 type Target = T;
1109
1110 fn deref(&self) -> &Self::Target {
1111 &self.inner
1112 }
1113}
1114
1115impl<T> Spanned for Context<T> {
1116 fn span(&self) -> Span {
1117 self.span
1118 }
1119}