Russo
Russo

Reputation: 3042

Solana Anchor Rust: How to convert a public key into an AccountInfo type

I know I can give my Solana Rust program an user's token account via a Context struct as shown in Anchor tutorial 2: https://project-serum.github.io/anchor/tutorials/tutorial-2.html#defining-a-program

#[derive(Accounts)]
pub struct Stake<'info> {
  pub user_reward_token_account: CpiAccount<'info, TokenAccount>,
  ...
}

But what if I want users to save that user's token account in certain user's storage account first, then let my Solana program get those token accounts from that user's storage account?

let user_acct = &ctx.accounts.user_acct;

Then when trying to mint some reward tokens to the user's token account:

let cpi_accounts = MintTo {
  mint: ctx.accounts.reward_mint.to_account_info(),
  to: user_acct.reward_user,
  authority: ctx.accounts.pg_signer.clone()
};

I got an error at compilation: expected struct anchor_lang::prelude::AccountInfo, found struct anchor_lang::prelude::Pubkey

but this to_account_info() method is not found in anchor_lang::prelude::Pubkey

I checked the Pubkey doc: https://docs.rs/anchor-lang/0.13.2/anchor_lang/prelude/struct.Pubkey.html

But it does not say anything about AccountInfo ...

Then I tried to make an AccountInfo struct from the reward_user address with the help of https://docs.rs/anchor-lang/0.13.2/anchor_lang/prelude/struct.AccountInfo.html:

let to_addr = AccountInfo {
  key: &user_acct.reward_user,
  is_signer: false,
  is_writable: true,
  lamports: Rc<RefCell<&'a mut u64>>,
  data: Rc<RefCell<&'a mut [u8]>>,
  owner: &user_pda.user_acct,
  executable: false,
  rent_epoch: u64,
};

But it is really hard and I do not know what the lamports, data, rent_epoch values are...

So how can I convert a public key into AccountInfo type?

Upvotes: 13

Views: 10849

Answers (2)

mega_creamery
mega_creamery

Reputation: 677

So for Sealevel to parallelise batches of instructions you need to provide an account in the list of accounts to be used by the program even if that account doesn't exist yet. As an account is being created it will need to have some lamports transferred to it to become rent exempt. Depositing lamports will require this account to have its state modified and as such it needs to be marked as writable.

I had problem relating to a potential, but unlikely concurrency issue where PDA seed would include state of a different account, counter and afterwards counter would be incremented. This is Solana's way of doing arrays that aren't capped by size constraints and can be indexed or looped over. I wanted each call to assemble a new account address on chain, rather than relaying on two clients not reading the counter state but one submitting transaction slightly slower and having it rejected. This is impossible.

What this means in practice is that the client always has to derive PDA and pass it to the program, even if program itself will do the same action again and then submit the transaction to the system program.

Upvotes: 3

yangli-io
yangli-io

Reputation: 17344

You will need to pass the accounts through the context in order to be able to access its data. This design allows Solana to parallelize transactions better by knowing which accounts and data is required before runtime.

Upvotes: 6

Related Questions