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

Hi there! Could you share a good resource/article that deeply explains why we always have to pass AccountInfo details from off-chain call to solana program and can’t create/init it on-chain?

Additionally @wdulkowski are you sure it’s a very minimum accounts to pass to create account on chain? I thought that we always have to pass “system program id” (11111111111111111111111111111111) too? When I tried your approach I’m getting an error which makes me think that passing system program id is obligatory:

    'Instruction references an unknown account 11111111111111111111111111111111',
    'Program C75CUoDoKg7MVZk4AtbsVQtTGU1SxYdThGFCt5PHbW3h consumed 50637 of 1400000 compute units',
    'Program C75CUoDoKg7MVZk4AtbsVQtTGU1SxYdThGFCt5PHbW3h failed: An account required by the instruction is missing'

Thanks for response in advance. I’m bit confused here so this is I might asked silly question.