0

I am trying to make a simple anchor app where an NFT is made and listed. Here is my code:

#[program]
 pub mod solft_practice {

use super::*;

pub fn initialize(ctx: Context<Initialize>, name: String, uri: String) -> ProgramResult {
    let system_program = ctx.accounts.system_program.to_account_info();
    let mint = ctx.accounts.mint.to_account_info();
    let spl_token_program = ctx.accounts.spl_token_program.to_account_info();
    let signer = ctx.accounts.signer.to_account_info();
    let metadata = ctx.accounts.metadata.to_account_info();
    let master_edition = ctx.accounts.master_edition.to_account_info();
    let sysvar_instructions = ctx.accounts.sysvar_instructions.to_account_info();

    msg!(
        "this is sysvarid: {}",
        anchor_lang::solana_program::sysvar::instructions::ID
    );
     CreateV1CpiBuilder::new(&system_program)
        .name(name)
        .uri(uri)
        .decimals(0)
        .authority(&signer)
        .payer(&signer)
        .system_program(&system_program)
        .update_authority(&signer, true)
        .metadata(&metadata)
        .master_edition(Some(&master_edition))
        .primary_sale_happened(false)
        .seller_fee_basis_points(500)
        .print_supply(PrintSupply::Zero)
        .is_mutable(false)
        .creators(vec![])
        .token_standard(TokenStandard::NonFungible)
        .mint(&mint, true)
        .sysvar_instructions(&sysvar_instructions)
        .spl_token_program(Some(&spl_token_program)).invoke_signed(&[
            &[&signer.key().to_bytes()[..]],
            &[&mint.key().to_bytes()[..]],
            &[&system_program.key().to_bytes()[..]],
        ])?;

    Ok(())

        
   }
}

#[derive(Accounts)]
pub struct Initialize<'info> {
///CHECK:
#[account(init, payer = signer,
 space = 1024,
 seeds = [
        b"metadata".as_ref(),
        mplID.to_bytes().as_ref(),   
        mint.key().as_ref(),
    ], bump
)]
pub metadata: AccountInfo<'info>,
///CHECK:
pub system_program: Program<'info, System>,
///CHECK:
pub sysvar_instructions: Program<'info, System>,
///CHECK:
#[account(init, payer = signer,
        space = 1024,
        seeds = [
        b"master".as_ref(),
        mplID.to_bytes().as_ref(), 
        mint.key().as_ref(),
        b"edition".as_ref(),
], bump
)]
pub master_edition: AccountInfo<'info>,
/// CHECK:
// #[account(mut)]
pub mint: AccountInfo<'info>,
///CHECK:
pub spl_token_program: AccountInfo<'info>,

#[account(mut)]
pub signer: Signer<'info>,
}

And here is TS code:

  it("Is initialized!", async () => {
try {
  const wallet = await getKeypairFromFile("~/.config/solana/id.json");

  const mplID = new anchor.web3.PublicKey(
    MPL_TOKEN_METADATA_PROGRAM_ID.toString()
  );

  const uri =
    "JSON_URI_ON_IPFS";

  const name = "NAME";

  const [metadata] = anchor.web3.PublicKey.findProgramAddressSync(
    [Buffer.from("metadata"), mplID.toBuffer(), mint.publicKey.toBuffer()],
    program.programId
  );
  const [master] = anchor.web3.PublicKey.findProgramAddressSync(
    [
      Buffer.from("master"),
      mplID.toBuffer(),
      mint.publicKey.toBuffer(),
      Buffer.from("edition"),
    ],
    program.programId
  );

  const tx = await program.methods
    .initialize(name, uri)
    .accountsPartial({
      mint: mint.publicKey,
      splTokenProgram: TOKEN_PROGRAM_ID,
      metadata,
      masterEdition: master,
      systemProgram: anchor.web3.SystemProgram.programId,
      sysvarInstructions: new anchor.web3.PublicKey(
        "11111111111111111111111111111111"
      ),
      signer: wallet.publicKey,
    })
    .signers([wallet])
    .rpc();

  console.log(tx);
  console.log(mint.publicKey.toBase58());
} catch (error) {
  console.log(error);

 });

And here is the error:

logs: [
'Program DG5fAyNpJHsbT25ESXkNVcqVw7SR4NudKGFFz1MG1W6G invoke [1]',
'Program log: Instruction: Initialize',
'Program 11111111111111111111111111111111 invoke [2]',
'Program 11111111111111111111111111111111 success',
'Program 11111111111111111111111111111111 invoke [2]',
'Program 11111111111111111111111111111111 success',
'Program log: this is sysvarid: Sysvar1nstructions1111111111111111111111111',
'Program DG5fAyNpJHsbT25ESXkNVcqVw7SR4NudKGFFz1MG1W6G consumed 31550 of 200000 compute 
 units',
'Program DG5fAyNpJHsbT25ESXkNVcqVw7SR4NudKGFFz1MG1W6G failed: Could not create program 
 address with signer seeds: Provided seeds do not result in a valid address'
  ],
  programErrorStack: ProgramErrorStack {
stack: [
  [PublicKey [PublicKey(DG5fAyNpJHsbT25ESXkNVcqVw7SR4NudKGFFz1MG1W6G)]]
    ]
  }
 }

I am using anchor v0.30.0 and mpl-token-metadata v4.1.2 Any help would be apprecidated.

Thanks in advance!

2 Answers 2

0

The program-derived addresses for the metaplex program are based on the metaplex program id, and not yours, so you'll need to do something like:

const [metadata] = anchor.web3.PublicKey.findProgramAddressSync(
    [Buffer.from("metadata"), mplID.toBuffer(), mint.publicKey.toBuffer()],
    MPL_TOKEN_METADATA_PROGRAM_ID
  );
  const [master] = anchor.web3.PublicKey.findProgramAddressSync(
    [
      Buffer.from("master"),
      mplID.toBuffer(),
      mint.publicKey.toBuffer(),
      Buffer.from("edition"),
    ],
    MPL_TOKEN_METADATA_PROGRAM_ID
  );

And then you'll also need to include the metaplex program id in your program (same as you've done with the system and SPL token programs).

And finally, you'll need to not instantiate the program-derived addresses for the metadata and master edition, which would make your accounts struct something like:

#[derive(Accounts)]
pub struct Initialize<'info> {
///CHECK:
pub metadata: AccountInfo<'info>,
///CHECK:
pub system_program: Program<'info, System>,
///CHECK:
pub sysvar_instructions: Program<'info, System>,
///CHECK:
pub master_edition: AccountInfo<'info>,
/// CHECK:
// #[account(mut)]
pub mint: AccountInfo<'info>,
///CHECK:
pub spl_token_program: AccountInfo<'info>,
/// CHECK:
pub mpl_token_metadata: AccountInfo<'info>,
#[account(mut)]
pub signer: Signer<'info>,
}
3
  • Wow thanks! But I've run into another problem. This one "Program DG5fAyNpJHsbT25ESXkNVcqVw7SR4NudKGFFz1MG1W6G failed: Cross-program invocation with unauthorized signer or writable account" . I suppose that it has to do something with signer seeds. Commented May 6 at 15:03
  • You shouldn't need signer seeds in your program -- the PDAs are all used by metaplex, so be sure to remove all references to those
    – Jon C
    Commented May 6 at 17:46
  • Okay, I tried without the signer seeds. When using just invoke, it gives the same error. When using neither invoke nor invoke_signed, the program gives no error but when I see the accounts (metadata, master and mint accounts) in the solana explorer, it shows nothing, says Account does not exist. Is this expected behaviour? I have no idea. Commented May 6 at 20:53
0

The master edition seeds are ["metadata", ProgramID, mint, "edition"] whereas you are passing in "master" as the first seed.

1
  • Okay Thanks!, but the error still persists. The issue is with the signer seeds according to the logs. It says: "Program DG5fAyNpJHsbT25ESXkNVcqVw7SR4NudKGFFz1MG1W6G failed: Could not create program address with signer seeds: Provided seeds do not result in a valid address" Commented May 2 at 8:57

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.