Reputation: 217
I am trying to write a Solana program which creates a PDA account for me on-chain. I can't get it to work and tbh, no idea what I am doing wrong :/
I have the following code in my Solana program:
let account_info_iter = &mut accounts.iter();
let initializer = next_account_info(account_info_iter)?;
if !initializer.is_signer {
return Err(ProgramError::MissingRequiredSignature);
}
let (pda, bump_seed) = Pubkey::find_program_address(&[b"admin_account"], program_id);
let admin_account = next_account_info(account_info_iter)?;
if admin_account.key != &pda {
return Err(CustomError::InvalidAdminAccount.into());
}
// we are checking if the account is rent exempt. In case it is, the account is already initialized
if **admin_account.try_borrow_lamports()? > 0 {
msg!("This account is already initialised. skipping");
return Ok(())
}
let lamports = Rent::default().minimum_balance(1);
let ix = solana_program::system_instruction::create_account(
initializer.key,
admin_account.key,
lamports,
1,
program_id,
);
// Sign and submit transaction
invoke_signed(
&ix,
&[initializer.clone(), admin_account.clone()],
&[&[b"admin_account"], &[&[bump_seed]]]
)?;
And here my Python script:
pda_account, nonce = PublicKey.find_program_address([b"admin_account"], PROGRAM_ID)
init_ix = TransactionInstruction(
data=bytes(1),
keys=[
AccountMeta(pubkey=ADMIN_KEYPAIR.public_key, is_signer=True, is_writable=False),
AccountMeta(pubkey=pda_account, is_signer=False, is_writable=True),
],
program_id=PROGRAM_ID,
)
transaction = Transaction()
transaction.add(init_pantos_token_ix)
utils.send_and_confirm_tx(CLIENT, transaction, ADMIN_KEYPAIR)
Whenever I execute the transaction I get the following error message:
Transaction simulation failed: Error processing Instruction 0: An account required by the instruction is missing
But what account is missing? I tried with the System Program but that gives me another error :/ Anyone any ideas?
Upvotes: 1
Views: 1431
Reputation: 8402
You do need to pass in the system program at the top-level, and then it's optional to pass into invoke_signed
. So your python script should do:
init_ix = TransactionInstruction(
data=bytes(1),
keys=[
AccountMeta(pubkey=ADMIN_KEYPAIR.public_key, is_signer=True, is_writable=True),
AccountMeta(pubkey=pda_account, is_signer=False, is_writable=True),
AccountMeta(pubkey=solana.system_program.SYS_PROGRAM_ID, is_signer=False, is_writable=False)
],
program_id=PROGRAM_ID,
)
Note that your ADMIN_KEYPAIR
will also need to be writable in order to move lamports from it to the pda account. With just these changes on the client-side, it should work.
Upvotes: 1