The best way to see what Anchor is currently doing is to use anchor expand
anchor expand
to see the expanded macros. Then you can pull that logic inside your own function.
- How can we check if a PDA account already exist within a function (not using struct).
I believe Anchor just checks the account balance, e.g. my_account.lamports()
.
Please note even if the account does exist, Anchor does a few extra things:
- Ensures the account size matches the requested space, even allocating extra space via CPI if required
- Ensures there is enough balance for the requested account size, even transferring lamports from payer via CPI, if it is short
- Ensures the right program is assigned to the account, even assigning owner via CPI if required
- How can we create a PDA account within a function (not using struct).
This is how Anchor does it under the hood:
let (__pda_address, __bump) = Pubkey::find_program_address(
&[<seeds>],
program_id,
);
let cpi_accounts = anchor_lang::system_program::CreateAccount {
from: payer.to_account_info(),
to: my_account.to_account_info(),
};
let cpi_context = anchor_lang::context::CpiContext::new(
system_program.to_account_info(),
cpi_accounts,
);
anchor_lang::system_program::create_account(
cpi_context
.with_signer(
&[
&[
<seeds>,
&[__bump][..],
][..],
],
),
lamports,
space as u64,
program_id,
)?;
- Is there a way to create a PDA account using struct only if doesn't exist already?
You can use init_if_needed
in your Accounts struct to instruct Anchor to create an account if only it does not already exist.
This feature is susceptible to re-initialisation attacks so it is not enabled by default. You can enable it in your Cargo.toml
by adding init-if-needed
feature to anchor-lang
.