2

Solana CLI 1.18, Anchor 0.30.

I have an existing basic Rust program that sets some attributes (a favorite number, a favorite color, and some hobbies) inside a PDA.

// Generate the PDA for the user's favorites
const favoritesPdaAndBump = web3.PublicKey.findProgramAddressSync(
  [Buffer.from("favorites"), user.publicKey.toBuffer()],
  program.programId
);

const favoritesPda = favoritesPdaAndBump[0];

// Make a transaction to write to the blockchain
await program.methods
  // Call the set_favorites instruction handler
  .setFavorites(favoriteNumber, favoriteColor, favoriteHobbies)
  .accounts({
    user: user.publicKey,
    favorites: favoritesPda, // The error is here
  })
  // Sign the transaction
  .signers([user])
  // Send the transaction to the cluster or RPC
  .rpc();

On the line mentioned above, TypeScript throws the error:

Object literal may only specify known properties, and 'favorites' does not exist in type 'ResolvedAccounts<{ name: "user"; writable: true; signer: true; } | { name: "favorites"; writable: true; pda: { seeds: [{ kind: "const"; value: [102, 97, 118, 111, 114, 105, 116, 101, 115]; }, { kind: "account"; path: "user"; }]; }; } | { ...; }>'

I have checked the seeds for favorites match the Rust program. Obviously favorites is still a PDA. My program even passes the tests if I use @ts-ignore above the warning.

But why am I getting the error?

My account constraints are as follows:

#[derive(Accounts)]
pub struct SetFavorites<'info> {
    #[account(mut)]
    pub user: Signer<'info>,

    #[account(
        init, 
        payer = user, 
        space = ANCHOR_DISCRIMINATOR_SIZE + Favorites::INIT_SPACE, 
        seeds=[b"favorites", user.key().as_ref()],
    bump)]
    pub favorites: Account<'info, Favorites>,

    pub system_program: Program<'info, System>,
}

1 Answer 1

3

This is because all PDAs resolve automatically in Anchor 0.30. The client does not need to know anything about the resolvable accounts, thus you can safely remove the web3.PublicKey.findProgramAddressSync call and the favorites account from the accounts call.

If you don't want Anchor to resolve these accounts automatically with type level safety, you can use accountsPartial method instead of accounts.

See https://www.anchor-lang.com/release-notes/0.30.0#account-resolution

2
  • Thanks! Just to clarify "and the favorites account from the accounts call" - it looks like I can remove .accounts() entirely, correct?
    – mikemaccana
    Commented May 30 at 13:30
  • If user is the provider wallet keypair, then you can remove both the accounts call and the signers call. Otherwise, if it's a generated keypair, both have to stay.
    – acheron
    Commented May 31 at 6:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.