Skip to main content

rialo_sol_derive_accounts/
lib.rs

1// Copyright (c) Subzero Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4#[allow(unused_extern_crates)]
5extern crate proc_macro;
6
7use proc_macro::TokenStream;
8use quote::ToTokens;
9use syn::parse_macro_input;
10
11/// Implements an [`Accounts`](./trait.Accounts.html) deserializer on the given
12/// struct. Can provide further functionality through the use of attributes.
13///
14/// # Table of Contents
15/// - [Instruction Attribute](#instruction-attribute)
16/// - [Constraints](#constraints)
17///
18/// # Instruction Attribute
19///
20/// You can access the instruction's arguments with the
21/// `#[instruction(..)]` attribute. You have to list them
22/// in the same order as in the instruction but you can
23/// omit all arguments after the last one you need.
24///
25/// # Example
26///
27/// ```ignore
28/// ...
29/// pub fn initialize(ctx: Context<Create>, bump: u8, authority: Pubkey, data: u64) -> rialo_sol_lang::Result<()> {
30///     ...
31///     Ok(())
32/// }
33/// ...
34/// #[derive(Accounts)]
35/// #[instruction(bump: u8)]
36/// pub struct Initialize<'info> {
37///     ...
38/// }
39/// ```
40///
41/// # Constraints
42///
43/// There are different types of constraints that can be applied with the `#[account(..)]` attribute.
44///
45/// Attributes may reference other data structures. When `<expr>` is used in the tables below, an arbitrary expression
46/// may be passed in as long as it evaluates to a value of the expected type, e.g. `owner = token_program.key()`. If `target_account`
47/// used, the `target_account` must exist in the struct and the `.key()` is implicit, e.g. `payer = authority`.
48///
49/// - [Normal Constraints](#normal-constraints)
50/// - [SPL Constraints](#spl-constraints)
51///
52/// # Normal Constraints
53/// <table>
54///     <thead>
55///         <tr>
56///             <th>Attribute</th>
57///             <th>Description</th>
58///         </tr>
59///     </thead>
60///     <tbody>
61///         <tr>
62///             <td>
63///                 <code>#[account(signer)]</code> <br><br><code>#[account(signer @ &lt;custom_error&gt;)]</code>
64///             </td>
65///             <td>
66///                 Checks the given account signed the transaction.<br>
67///                 Custom errors are supported via <code>@</code>.<br>
68///                 Consider using the <code>Signer</code> type if you would only have this constraint on the account.<br><br>
69///                 Example:
70///                 <pre><code>
71/// #[account(signer)]
72/// pub authority: AccountInfo<'info>,
73/// #[account(signer @ MyError::MyErrorCode)]
74/// pub payer: AccountInfo<'info>
75///                 </code></pre>
76///             </td>
77///         </tr>
78///         <tr>
79///             <td>
80///                 <code>#[account(mut)]</code> <br><br><code>#[account(mut @ &lt;custom_error&gt;)]</code>
81///             </td>
82///             <td>
83///                 Checks the given account is mutable.<br>
84///                 Makes anchor persist any state changes.<br>
85///                 Custom errors are supported via <code>@</code>.<br><br>
86///                 Example:
87///                 <pre><code>
88/// #[account(mut)]
89/// pub data_account: Account<'info, MyData>,
90/// #[account(mut @ MyError::MyErrorCode)]
91/// pub data_account_two: Account<'info, MyData>
92///                 </code></pre>
93///             </td>
94///         </tr>
95///         <tr>
96///             <td>
97///                 <code>#[account(init, payer = &lt;target_account&gt;, space = &lt;num_bytes&gt;)]</code>
98///             </td>
99///             <td>
100///                 Creates the account via a CPI to the system program and
101///                 initializes it (sets its account discriminator). The annotated account is required to sign for this instruction
102///                 unless `seeds` is provided. <br>
103///                 Marks the account as mutable and is mutually exclusive with <code>mut</code>.<br>
104///                 Makes the account rent exempt unless skipped with <code>rent_exempt = skip</code>.<br><br>
105///                 Use <code>#[account(zero)]</code> for accounts larger than 10 Kibibyte.<br><br>
106///                 <code>init</code> has to be used with additional constraints:
107///                 <ul>
108///                     <li>
109///                         Requires the <code>payer</code> constraint to also be on the account.
110///                         The <code>payer</code> account pays for the
111///                         account creation.
112///                     </li>
113///                     <li>
114///                         Requires the system program to exist on the struct
115///                         and be called <code>system_program</code>.
116///                     </li>
117///                     <li>
118///                         Requires that the <code>space</code> constraint is specified.
119///                         When using the <code>space</code> constraint, one must remember to add 8 to it
120///                         which is the size of the account discriminator. This only has to be done
121///                         for accounts owned by anchor programs.<br>
122///                         The given space number is the size of the account in bytes, so accounts that hold
123///                         a variable number of items such as a <code>Vec</code> should allocate sufficient space for all items that may
124///                         be added to the data structure because account size is fixed.
125///                         Check out the <a href = "https://www.anchor-lang.com/docs/space" target = "_blank" rel = "noopener noreferrer">space reference</a>
126///                         and the <a href = "https://borsh.io/" target = "_blank" rel = "noopener noreferrer">borsh library</a>
127///                         (which anchor uses under the hood for serialization) specification to learn how much
128///                         space different data structures require.
129///                     </li>
130///                 <br>
131///                 Example:
132///                 <pre>
133/// #[account]
134/// pub struct MyData {
135/// &nbsp;&nbsp;&nbsp;&nbsp;pub data: u64
136/// }&#10;
137/// #[derive(Accounts)]
138/// pub struct Initialize<'info> {
139/// &nbsp;&nbsp;&nbsp;&nbsp;#[account(init, payer = payer, space = 8 + 8)]
140/// &nbsp;&nbsp;&nbsp;&nbsp;pub data_account_two: Account<'info, MyData>,
141/// &nbsp;&nbsp;&nbsp;&nbsp;#[account(mut)]
142/// &nbsp;&nbsp;&nbsp;&nbsp;pub payer: Signer<'info>,
143/// &nbsp;&nbsp;&nbsp;&nbsp;pub system_program: Program<'info, System>,
144/// }
145///                 </pre>
146///                 </ul>
147///                 <code>init</code> can be combined with other constraints (at the same time):
148///                 <ul>
149///                     <li>
150///                         By default <code>init</code> sets the owner field of the created account to the
151///                         currently executing program. Add the <code>owner</code> constraint to specify a
152///                         different program owner.
153///                     </li>
154///                     <li>
155///                         Use the <code>seeds</code> constraint together with <code>bump</code>to create PDAs.<br>
156///                         <code>init</code> uses <code>find_program_address</code> to calculate the pda so the
157///                         bump value can be left empty.<br>
158///                         However, if you want to use the bump in your instruction,
159///                         you can pass it in as instruction data and set the bump value like shown in the example,
160///                         using the <code>instruction_data</code> attribute.
161///                         Anchor will then check that the bump returned by <code>find_program_address</code> equals
162///                         the bump in the instruction data.<br>
163///                         <code>seeds::program</code> cannot be used together with init because the creation of an
164///                         account requires its signature which for PDAs only the currently executing program can provide.
165///                     </li>
166///                 </ul>
167///                 Example:
168///                 <pre>
169/// #[derive(Accounts)]
170/// #[instruction(bump: u8)]
171/// pub struct Initialize<'info> {
172/// &nbsp;&nbsp;&nbsp;&nbsp;#[account(
173/// &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;init, payer = payer, space = 8 + 8
174/// &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;seeds = [b"example_seed"], bump = bump
175/// &nbsp;&nbsp;&nbsp;&nbsp;)]
176/// &nbsp;&nbsp;&nbsp;&nbsp;pub pda_data_account: Account<'info, MyData>,
177/// &nbsp;&nbsp;&nbsp;&nbsp;#[account(
178/// &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;init, payer = payer,
179/// &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;space = 8 + 8, owner = other_program.key()
180/// &nbsp;&nbsp;&nbsp;&nbsp;)]
181/// &nbsp;&nbsp;&nbsp;&nbsp;pub account_for_other_program: AccountInfo<'info>,
182/// &nbsp;&nbsp;&nbsp;&nbsp;#[account(
183/// &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;init, payer = payer, space = 8 + 8,
184/// &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;owner = other_program.key(),
185/// &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;seeds = [b"other_seed"], bump
186/// &nbsp;&nbsp;&nbsp;&nbsp;)]
187/// &nbsp;&nbsp;&nbsp;&nbsp;pub pda_for_other_program: AccountInfo<'info>,
188/// &nbsp;&nbsp;&nbsp;&nbsp;#[account(mut)]
189/// &nbsp;&nbsp;&nbsp;&nbsp;pub payer: Signer<'info>,
190/// &nbsp;&nbsp;&nbsp;&nbsp;pub system_program: Program<'info, System>,
191/// &nbsp;&nbsp;&nbsp;&nbsp;pub other_program: Program<'info, OtherProgram>
192/// }
193///                 </pre>
194///             </td>
195///         </tr>
196///         <tr>
197///             <td>
198///                 <code>#[account(init_if_needed, payer = &lt;target_account&gt;)]</code><br><br>
199///                 <code>#[account(init_if_needed, payer = &lt;target_account&gt;, space = &lt;num_bytes&gt;)]</code>
200///             </td>
201///             <td>
202///                 Exact same functionality as the <code>init</code> constraint but only runs if the account does not exist yet.<br>
203///                 If the account does exist, it still checks whether the given init constraints are correct,
204///                 e.g. that the account has the expected amount of space and, if it's a PDA, the correct seeds etc.<br><br>
205///                 This feature should be used with care and is therefore behind a feature flag.
206///                 You can enable it by importing <code>anchor-lang</code> with the <code>init-if-needed</code> cargo feature.<br>
207///                 When using <code>init_if_needed</code>, you need to make sure you properly protect yourself
208///                 against re-initialization attacks. You need to include checks in your code that check
209///                 that the initialized account cannot be reset to its initial settings after the first time it was
210///                 initialized (unless that it what you want).<br>
211///                 Because of the possibility of re-initialization attacks and the general guideline that instructions
212///                 should avoid having multiple execution flows (which is important so they remain easy to understand),
213///                 consider breaking up your instruction into two instructions - one for initializing and one for using
214///                 the account - unless you have a good reason not to do so.
215///                 <br><br>
216///                 Example:
217///                 <pre>
218/// #[account]
219/// #[derive(Default)]
220/// pub struct MyData {
221/// &nbsp;&nbsp;&nbsp;&nbsp;pub data: u64
222/// }&#10;
223/// #[account]
224/// pub struct OtherData {
225/// &nbsp;&nbsp;&nbsp;&nbsp;pub data: u64
226/// }&#10;
227/// #[derive(Accounts)]
228/// pub struct Initialize<'info> {
229/// &nbsp;&nbsp;&nbsp;&nbsp;#[account(init_if_needed, payer = payer)]
230/// &nbsp;&nbsp;&nbsp;&nbsp;pub data_account: Account<'info, MyData>,
231/// &nbsp;&nbsp;&nbsp;&nbsp;#[account(init_if_needed, payer = payer, space = 8 + 8)]
232/// &nbsp;&nbsp;&nbsp;&nbsp;pub data_account_two: Account<'info, OtherData>,
233/// &nbsp;&nbsp;&nbsp;&nbsp;#[account(mut)]
234/// &nbsp;&nbsp;&nbsp;&nbsp;pub payer: Signer<'info>,
235/// &nbsp;&nbsp;&nbsp;&nbsp;pub system_program: Program<'info, System>
236/// }
237///                 </pre>
238///             </td>
239///         </tr>
240///         <tr>
241///             <td>
242///                 <code>#[account(seeds = &lt;seeds&gt;, bump)]</code><br><br>
243///                 <code>#[account(seeds = &lt;seeds&gt;, bump, seeds::program = &lt;expr&gt;)]</code><br><br>
244///                 <code>#[account(seeds = &lt;seeds&gt;, bump = &lt;expr&gt;)]</code><br><br>
245///                 <code>#[account(seeds = &lt;seeds&gt;, bump = &lt;expr&gt;, seeds::program = &lt;expr&gt;)]</code><br><br>
246///             </td>
247///             <td>
248///                 Checks that given account is a PDA derived from the currently executing program,
249///                 the seeds, and if provided, the bump. If not provided, anchor uses the canonical
250///                 bump. <br>
251///                 Add <code>seeds::program = &lt;expr&gt;</code> to derive the PDA from a different
252///                 program than the currently executing one.<br>
253///                 This constraint behaves slightly differently when used with <code>init</code>.
254///                 See its description.
255///                 <br><br>
256///                 Example:
257///                 <pre><code>
258/// #[derive(Accounts)]
259/// #[instruction(first_bump: u8, second_bump: u8)]
260/// pub struct Example {
261///     #[account(seeds = [b"example_seed"], bump)]
262///     pub canonical_pda: AccountInfo<'info>,
263///     #[account(
264///         seeds = [b"example_seed"],
265///         bump,
266///         seeds::program = other_program.key()
267///     )]
268///     pub canonical_pda_two: AccountInfo<'info>,
269///     #[account(seeds = [b"other_seed"], bump = first_bump)]
270///     pub arbitrary_pda: AccountInfo<'info>
271///     #[account(
272///         seeds = [b"other_seed"],
273///         bump = second_bump,
274///         seeds::program = other_program.key()
275///     )]
276///     pub arbitrary_pda_two: AccountInfo<'info>,
277///     pub other_program: Program<'info, OtherProgram>
278/// }
279///                 </code></pre>
280///             </td>
281///         </tr>
282///         <tr>
283///             <td>
284///                 <code>#[account(has_one = &lt;target_account&gt;)]</code><br><br>
285///                 <code>#[account(has_one = &lt;target_account&gt; @ &lt;custom_error&gt;)]</code>
286///             </td>
287///             <td>
288///                 Checks the <code>target_account</code> field on the account matches the
289///                 key of the <code>target_account</code> field in the Accounts struct.<br>
290///                 Custom errors are supported via <code>@</code>.<br><br>
291///                 Example:
292///                 <pre><code>
293/// #[account(mut, has_one = authority)]
294/// pub data: Account<'info, MyData>,
295/// pub authority: Signer<'info>
296///                 </code></pre>
297///                 In this example <code>has_one</code> checks that <code>data.authority = authority.key()</code>
298///             </td>
299///         </tr>
300///         <tr>
301///             <td>
302///                 <code>#[account(address = &lt;expr&gt;)]</code><br><br>
303///                 <code>#[account(address = &lt;expr&gt; @ &lt;custom_error&gt;)]</code>
304///             </td>
305///             <td>
306///                 Checks the account key matches the pubkey.<br>
307///                 Custom errors are supported via <code>@</code>.<br><br>
308///                 Example:
309///                 <pre><code>
310/// #[account(address = crate::ID)]
311/// pub data: Account<'info, MyData>,
312/// #[account(address = crate::ID @ MyError::MyErrorCode)]
313/// pub data_two: Account<'info, MyData>
314///                 </code></pre>
315///             </td>
316///         </tr>
317///         <tr>
318///             <td>
319///                 <code>#[account(owner = &lt;expr&gt;)]</code><br><br>
320///                 <code>#[account(owner = &lt;expr&gt; @ &lt;custom_error&gt;)]</code>
321///             </td>
322///             <td>
323///                 Checks the account owner matches <code>expr</code>.<br>
324///                 Custom errors are supported via <code>@</code>.<br><br>
325///                 Example:
326///                 <pre><code>
327/// #[account(owner = Token::ID @ MyError::MyErrorCode)]
328/// pub data: Account<'info, MyData>,
329/// #[account(owner = token_program.key())]
330/// pub data_two: Account<'info, MyData>,
331/// pub token_program: Program<'info, Token>
332///                 </code></pre>
333///             </td>
334///         </tr>
335///         <tr>
336///             <td>
337///                 <code>#[account(executable)]</code>
338///             </td>
339///             <td>
340///                 Checks the account is executable (i.e. the account is a program).<br>
341///                 You may want to use the <code>Program</code> type instead.<br><br>
342///                 Example:
343///                 <pre><code>
344/// #[account(executable)]
345/// pub my_program: AccountInfo<'info>
346///                 </code></pre>
347///             </td>
348///         </tr>
349///         <tr>
350///             <td>
351///                 <code>#[account(rent_exempt = skip)]</code><br><br>
352///                 <code>#[account(rent_exempt = enforce)]</code>
353///             </td>
354///             <td>
355///                 Enforces rent exemption with <code>= enforce</code>.<br>
356///                 Skips rent exemption check that would normally be done
357///                 through other constraints with <code>= skip</code>,
358///                 e.g. when used with the <code>zero</code> constraint<br><br>
359///                 Example:
360///                 <pre><code>
361/// #[account(zero, rent_exempt = skip)]
362/// pub skipped_account: Account<'info, MyData>,
363/// #[account(rent_exempt = enforce)]
364/// pub enforced_account: AccountInfo<'info>
365///                 </code></pre>
366///             </td>
367///         </tr>
368///         <tr>
369///             <td>
370///                 <code>#[account(zero)]</code>
371///             </td>
372///             <td>
373///                 Checks the account discriminator is zero.<br>
374///                 Enforces rent exemption unless skipped with <code>rent_exempt = skip</code>.<br><br>
375///                 Use this constraint if you want to create an account in a previous instruction
376///                 and then initialize it in your instruction instead of using <code>init</code>.
377///                 This is necessary for accounts that are larger than 10 Kibibyte because those
378///                 accounts cannot be created via a CPI (which is what <code>init</code> would do).<br><br>
379///                 Anchor adds internal data to the account when using <code>zero</code> just like it
380///                 does with <code>init</code> which is why <code>zero</code> implies <code>mut</code>.
381///                 <br><br>
382///                 Example:
383///                 <pre><code>
384/// #[account(zero)]
385/// pub my_account: Account<'info, MyData>
386///                 </code></pre>
387///             </td>
388///         </tr>
389///         <tr>
390///             <td>
391///                 <code>#[account(close = &lt;target_account&gt;)]</code>
392///             </td>
393///             <td>
394///                 Closes the account by:<br>
395///                 &nbsp;&nbsp;&nbsp;&nbsp;- Sending the kelvins to the specified account<br>
396///                 &nbsp;&nbsp;&nbsp;&nbsp;- Assigning the owner to the System Program<br>
397///                 &nbsp;&nbsp;&nbsp;&nbsp;- Resetting the data of the account<br><br>
398///                 Requires <code>mut</code> to exist on the account.
399///                 <br><br>
400///                 Example:
401///                 <pre><code>
402/// #[account(mut, close = receiver)]
403/// pub data_account: Account<'info, MyData>,
404/// #[account(mut)]
405/// pub receiver: SystemAccount<'info>
406///                 </code></pre>
407///             </td>
408///         </tr>
409///         <tr>
410///             <td>
411///                 <code>#[account(constraint = &lt;expr&gt;)]</code><br><br><code>#[account(constraint = &lt;expr&gt; @ &lt;custom_error&gt;)]</code>
412///             </td>
413///             <td>
414///                 Constraint that checks whether the given expression evaluates to true.<br>
415///                 Use this when no other constraint fits your use case.
416///                 <br><br>
417///                 Example:
418///                 <pre><code>
419/// #[account(constraint = one.keys[0].age == two.apple.age)]
420/// pub one: Account<'info, MyData>,
421/// pub two: Account<'info, OtherData>
422///                 </code></pre>
423///             </td>
424///         </tr>
425///         <tr>
426///             <td>
427///                 <code>#[account(realloc = &lt;space&gt;, realloc::payer = &lt;target&gt;, realloc::zero = &lt;bool&gt;)]</code>
428///             </td>
429///             <td>
430///                 Used to <a href="https://docs.rs/solana-program/latest/rialo_s_program/account_info/struct.AccountInfo.html#method.realloc" target = "_blank" rel = "noopener noreferrer">realloc</a>
431///                 program account space at the beginning of an instruction.
432///                 <br><br>
433///                 The account must be marked as <code>mut</code> and applied to either <code>Account</code> or <code>AccountLoader</code> types.
434///                 <br><br>
435///                 If the change in account data length is additive, kelvins will be transferred from the <code>realloc::payer</code> into the
436///                 program account in order to maintain rent exemption. Likewise, if the change is subtractive, kelvins will be transferred from
437///                 the program account back into the <code>realloc::payer</code>.
438///                 <br><br>
439///                 The <code>realloc::zero</code> constraint is required in order to determine whether the new memory should be zero initialized after
440///                 reallocation. Please read the documentation on the <code>AccountInfo::realloc</code> function linked above to understand the
441///                 caveats regarding compute units when providing <code>true</code> or <code>false</code> to this flag.
442///                 <br><br>
443///                 The manual use of `AccountInfo::realloc` is discouraged in favor of the `realloc` constraint group due to the lack of native runtime checks
444///                 to prevent reallocation over the `MAX_PERMITTED_DATA_INCREASE` limit (which can unintentionally cause account data overwrite other accounts).
445///                 The constraint group also ensure account reallocation idempotency but checking and restricting duplicate account reallocation within a single ix.
446///                 <br><br>
447///                 Example:
448///                 <pre>
449/// #[derive(Accounts)]
450/// pub struct Example {
451///     #[account(mut)]
452///     pub payer: Signer<'info>,
453///     #[account(
454///         mut,
455///         seeds = [b"example"],
456///         bump,
457///         realloc = 8 + `std::mem::size_of::&lt;MyType&gt;`() + 100,
458///         realloc::payer = payer,
459///         realloc::zero = false,
460///     )]
461///     pub acc: Account<'info, MyType>,
462///     pub system_program: Program<'info, System>,
463/// }
464///                 </pre>
465///             </td>
466///         </tr>
467///     </tbody>
468/// </table>
469///
470/// # SPL Constraints
471///
472/// Anchor provides constraints that make verifying SPL accounts easier.
473///
474/// <table>
475///     <thead>
476///         <tr>
477///             <th>Attribute</th>
478///             <th>Description</th>
479///         </tr>
480///     </thead>
481///     <tbody>
482///         <tr>
483///             <td>
484///                 <code>#[account(token::mint = &lt;target_account&gt;, token::authority = &lt;target_account&gt;)]</code>
485///             <br><br>
486///                 <code>#[account(token::mint = &lt;target_account&gt;, token::authority = &lt;target_account&gt;, token::token_program = &lt;target_account&gt;)]</code>
487///             </td>
488///             <td>
489///                 Can be used as a check or with <code>init</code> to create a token
490///                 account with the given mint address and authority.<br>
491///                  When used as a check, it's possible to only specify a subset of the constraints.
492///                 <br><br>
493///                 Example:
494///                 <pre>
495/// use anchor_spl::{mint, token::{TokenAccount, Mint, Token}};
496/// ...&#10;
497/// #[account(
498///     init,
499///     payer = payer,
500///     token::mint = mint,
501///     token::authority = payer,
502/// )]
503/// pub token: Account<'info, TokenAccount>,
504/// #[account(address = mint::USDC)]
505/// pub mint: Account<'info, Mint>,
506/// #[account(mut)]
507/// pub payer: Signer<'info>,
508/// pub token_program: Program<'info, Token>,
509/// pub system_program: Program<'info, System>
510///                 </pre>
511///             </td>
512///         </tr>
513///         <tr>
514///             <td>
515///                 <code>#[account(mint::authority = &lt;target_account&gt;, mint::decimals = &lt;expr&gt;)]</code>
516///                 <br><br>
517///                 <code>#[account(mint::authority = &lt;target_account&gt;, mint::decimals = &lt;expr&gt;, mint::freeze_authority = &lt;target_account&gt;)]</code>
518///             </td>
519///             <td>
520///                 Can be used as a check or with <code>init</code> to create a mint
521///                 account with the given mint decimals and mint authority.<br>
522///                 The freeze authority is optional when used with <code>init</code>.<br>
523///                 When used as a check, it's possible to only specify a subset of the constraints.
524///                 <br><br>
525///                 Example:
526///                 <pre>
527/// use anchor_spl::token::{Mint, Token};
528/// ...&#10;
529/// #[account(
530///     init,
531///     payer = payer,
532///     mint::decimals = 9,
533///     mint::authority = payer,
534/// )]
535/// pub mint_one: Account<'info, Mint>,
536/// #[account(
537///     init,
538///     payer = payer,
539///     mint::decimals = 9,
540///     mint::authority = payer,
541///     mint::freeze_authority = payer
542/// )]
543/// pub mint_two: Account<'info, Mint>,
544/// #[account(mut)]
545/// pub payer: Signer<'info>,
546/// pub token_program: Program<'info, Token>,
547/// pub system_program: Program<'info, System>
548///                 </pre>
549///             </td>
550///         </tr>
551///         <tr>
552///             <td>
553///                 <code>#[account(associated_token::mint = &lt;target_account&gt;, associated_token::authority = &lt;target_account&gt;)]</code>
554///                <br><br>
555///                 <code>#[account(associated_token::mint = &lt;target_account&gt;, associated_token::authority = &lt;target_account&gt;, associated_token::token_program = &lt;target_account&gt;)]</code>
556///             </td>
557///             <td>
558///                 Can be used as a standalone as a check or with <code>init</code> to create an associated token
559///                 account with the given mint address and authority.
560///                 <br><br>
561///                 Example:
562///                 <pre>
563/// use anchor_spl::{
564///     associated_token::AssociatedToken,
565///     mint,
566///     token::{TokenAccount, Mint, Token}
567/// };
568/// ...&#10;
569/// #[account(
570///     init,
571///     payer = payer,
572///     associated_token::mint = mint,
573///     associated_token::authority = payer,
574/// )]
575/// pub token: Account<'info, TokenAccount>,
576/// #[account(
577///     associated_token::mint = mint,
578///     associated_token::authority = payer,
579/// )]
580/// pub second_token: Account<'info, TokenAccount>,
581/// #[account(address = mint::USDC)]
582/// pub mint: Account<'info, Mint>,
583/// #[account(mut)]
584/// pub payer: Signer<'info>,
585/// pub token_program: Program<'info, Token>,
586/// pub associated_token_program: Program<'info, AssociatedToken>,
587/// pub system_program: Program<'info, System>
588///                 </pre>
589///             </td>
590///         </tr><tr>
591///             <td>
592///                 <code>#[account(*::token_program = &lt;target_account&gt;)]</code>
593///             </td>
594///             <td>
595///                 The <code>token_program</code> can optionally be overridden.
596///                 <br><br>
597///                 Example:
598///                 <pre>
599/// use anchor_spl::token_interface::{TokenInterface, TokenAccount, Mint};
600/// ...&#10;
601/// #[account(
602///     mint::token_program = token_a_token_program,
603/// )]
604/// pub token_a_mint: InterfaceAccount<'info, Mint>,
605/// #[account(
606///     mint::token_program = token_b_token_program,
607/// )]
608/// pub token_b_mint: InterfaceAccount<'info, Mint>,
609/// #[account(
610///     init,
611///     payer = payer,
612///     token::mint = token_a_mint,
613///     token::authority = payer,
614///     token::token_program = token_a_token_program,
615/// )]
616/// pub token_a_account: InterfaceAccount<'info, TokenAccount>,
617/// #[account(
618///     init,
619///     payer = payer,
620///     token::mint = token_b_mint,
621///     token::authority = payer,
622///     token::token_program = token_b_token_program,
623/// )]
624/// pub token_b_account: InterfaceAccount<'info, TokenAccount>,
625/// pub token_a_token_program: Interface<'info, TokenInterface>,
626/// pub token_b_token_program: Interface<'info, TokenInterface>,
627/// #[account(mut)]
628/// pub payer: Signer<'info>,
629/// pub system_program: Program<'info, System>
630///                 </pre>
631///             </td>
632///         </tr>
633///     </tbody>
634/// </table>
635#[proc_macro_derive(Accounts, attributes(account, instruction))]
636pub fn derive_accounts(item: TokenStream) -> TokenStream {
637    parse_macro_input!(item as rialo_sol_syn::AccountsStruct)
638        .to_token_stream()
639        .into()
640}