lib.rs 31 KB

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