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