lib.rs 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. extern crate proc_macro;
  2. use anchor_syn::codegen::accounts as accounts_codegen;
  3. use anchor_syn::parser::accounts as accounts_parser;
  4. use proc_macro::TokenStream;
  5. use syn::parse_macro_input;
  6. /// Implements an [`Accounts`](./trait.Accounts.html) deserializer on the given
  7. /// struct, applying any constraints specified via inert `#[account(..)]`
  8. /// attributes upon deserialization.
  9. ///
  10. /// # Example
  11. ///
  12. /// ```ignore
  13. /// #[derive(Accounts)]
  14. /// pub struct Auth<'info> {
  15. /// #[account(mut, has_one = authority)]
  16. /// pub data: ProgramAccount<'info, MyData>,
  17. /// #[account(signer)]
  18. /// pub authority: AccountInfo<'info>,
  19. /// }
  20. ///
  21. /// #[account]
  22. /// pub struct MyData {
  23. /// authority: Pubkey,
  24. /// protected_data: u64,
  25. /// }
  26. /// ```
  27. ///
  28. /// Here, any instance of the `Auth` struct created via
  29. /// [`try_accounts`](trait.Accounts.html#tymethod.try_accounts) is guaranteed
  30. /// to have been both
  31. ///
  32. /// * Signed by `authority`.
  33. /// * Checked that `&data.authority == authority.key`.
  34. ///
  35. /// The full list of available attributes is as follows.
  36. ///
  37. /// | Attribute | Location | Description |
  38. /// |:--|:--|:--|
  39. /// | `#[account(signer)]` | On raw `AccountInfo` structs. | Checks the given account signed the transaction. |
  40. /// | `#[account(mut)]` | On `AccountInfo`, `ProgramAccount` or `CpiAccount` structs. | Marks the account as mutable and persists the state transition. |
  41. /// | `#[account(init)]` | On `ProgramAccount` structs. | Marks the account as being initialized, skipping the account discriminator check. When using `init`, a `rent` `Sysvar` must be present in the `Accounts` struct. |
  42. /// | `#[account(belongs_to = <target>)]` | On `ProgramAccount` or `CpiAccount` structs | Checks the `target` field on the account matches the `target` field in the struct deriving `Accounts`. |
  43. /// | `#[account(has_one = <target>)]` | On `ProgramAccount` or `CpiAccount` structs | Semantically different, but otherwise the same as `belongs_to`. |
  44. /// | `#[account(seeds = [<seeds>])]` | On `AccountInfo` structs | Seeds for the program derived address an `AccountInfo` struct represents. |
  45. /// | `#[account("<literal>")]` | On any type deriving `Accounts` | Executes the given code literal as a constraint. The literal should evaluate to a boolean. |
  46. /// | `#[account(rent_exempt = <skip>)]` | On `AccountInfo` or `ProgramAccount` structs | Optional attribute to skip the rent exemption check. By default, all accounts marked with `#[account(init)]` will be rent exempt, and so this should rarely (if ever) be used. Similarly, omitting `= skip` will mark the account rent exempt. |
  47. /// | `#[account(executable)]` | On `AccountInfo` structs | Checks the given account is an executable program. |
  48. /// | `#[account(state = <target>)]` | On `CpiState` structs | Checks the given state is the canonical state account for the target program. |
  49. /// | `#[account(owner = <target>)]` | On `CpiState`, `CpiAccount`, and `AccountInfo` | Checks the account owner matches the target. |
  50. /// | `#[account(associated = <target>, with? = <target>, payer? = <target>, space? = "<literal>")]` | On `ProgramAccount` | Creates an associated program account at a program derived address. `associated` is the SOL address to create the account for. `with` is an optional association, for example, a `Mint` account in the SPL token program. `payer` is an optional account to pay for the account creation, defaulting to the `associated` target if none is given. `space` is an optional literal specifying how large the account is, defaulting to the account's serialized `Default::default` size (+ 8 for the account discriminator) if none is given. When creating an associated account, a `rent` `Sysvar` and `system_program` `AccountInfo` must be present in the `Accounts` struct. |
  51. // TODO: How do we make the markdown render correctly without putting everything
  52. // on absurdly long lines?
  53. #[proc_macro_derive(Accounts, attributes(account))]
  54. pub fn derive_anchor_deserialize(item: TokenStream) -> TokenStream {
  55. let strct = parse_macro_input!(item as syn::ItemStruct);
  56. let tts = accounts_codegen::generate(accounts_parser::parse(&strct));
  57. proc_macro::TokenStream::from(tts)
  58. }