How do you create an account on chain?

I’m trying to find an example that does it.

It seems all of the PDAs examples that I’ve seen so far have addresses and related account information generated off chain and then extracted in the list of accounts in the program as such:

	let mut accounts_iter = accounts.iter();
	let funder = next_account_info(&mut accounts_iter)?;
        let account_to_init = next_account_info(&mut accounts_iter)?;

But then there is this function, which seems like it can find a valid PDA on-chan even if it means more calculation.

let (pda, bump) = Pubkey::find_program_address(&[seed.as_bytes()], program_id);

Just not really sure how to proceed with the pda from above as the invoke_signed function requires an AccountInfo struct rather than solely the public key of the PDA.

In the hello-world counter example there is a test that has following code:

      let program_id = Pubkey::default();
        let key = Pubkey::default();
        let mut lamports = 0;
        let mut data = vec![0; mem::size_of::<u32>()];
        let owner = Pubkey::default();
        let account = AccountInfo::new(
            &key,
            false,
            true,
            &mut lamports,
            &mut data,
            &owner,
            false,
            Epoch::default(),
        );

Is this how you would instantiate an AccountInfo struct so that it could be signed and submitted with invoke_sign on chain?

I know this is a bit of a niche question since every single example extracts account that are passed to it and those either already exist somewhere or have been assembled and serialised in the frontend.

Thanks for help

can post here the solution? I have the same issue and maybe there are many others in this situation. Thanks!

I’m not sure how to do this, I’ve never had to do it before, but it seems like the block posted above that does AccountInfo::new is worth a try.

I found something:
/// Convert (&'a Pubkey, bool, &'a mut T) where T: Account into an
/// AccountInfo.
impl<'a, T: Account> IntoAccountInfo<'a> for (&'a Pubkey, bool, &'a mut T) {
fn into_account_info(self) → AccountInfo<'a> {
let (key, is_signer, account) = self;
let (lamports, data, owner, executable, rent_epoch) = account.get();
AccountInfo::new(
key, is_signer, false, lamports, data, owner, executable, rent_epoch,
)
}
}
This seems to convert a pubkey to accountInfo, but I don’t know what type of account to give it there. I’m quite new to rust and solana.

You can’t do it, you need pass all of the accounts that will be read/written to the program.

Client always has to pass all the accounts, as the account is being created it will need to have lamports dropped off so Sealevel needs to know that this account will be mutable, even if it doesn’t exist yet.

Afterwards this is the syntax


	if **account_to_init.try_borrow_lamports()? > 0 {
		msg!("This account is already initialised that account, skipping");
		return Ok(());
	}
	
	let lamports = Rent::default().minimum_balance(account_size as usize);

	// Assemble PDA creation instruction
	let ix = solana_program::system_instruction::create_account(
		funder.key,
		account_to_init.key,
		lamports,
		account_size as u64,
		program_id,
	);

	// Sign and submit transaction
	invoke_signed(
		&ix,
		&[funder.clone(), account_to_init.clone()],
		&[&[seed.as_bytes(), &[bump]]],
	)?;

This stack overflow question asks the same thing.

2 Likes