metaplex-foundation / mpl-token-metadata

Program to attach additional data to Fungible or Non-Fungible tokens on Solana.
https://developers.metaplex.com/token-metadata
Other
98 stars 42 forks source link

Instruction not supported for ProgrammableNonFungible assets [0x99] #78

Closed zikyfranky closed 5 months ago

zikyfranky commented 5 months ago

I'm trying to initialize metadata for my FUNGIBLE token (no edition + has decimals), but whenever I call the instruction, I get the 0x99 error message, for some reason, metadata thinks my token is a ProgrammableNonFungible token.

Here's the transaction log

"Program metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s invoke [2]" "Program log: Instruction not supported for ProgrammableNonFungible assets" "Program metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s consumed 6199 of 313203 compute units" "Program metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s failed: custom program error: 0x99"

Here is my initializer code

#[derive(Accounts)]
#[instruction(params: InitTokenParams)]
pub struct InitializeMetadata<'info> {
    #[account(mut)]
    pub admin: Signer<'info>,
    /// CHECK: It'd be Created by Metaplex
    #[account(mut)]
    pub metadata: UncheckedAccount<'info>,

    #[account(
    mut,
        seeds = [MINT_SEED],
        bump,
        mint::decimals = params.decimals,
        mint::authority = mint,
    mint::freeze_authority = mint,
    )]
    pub mint: InterfaceAccount<'info, Mint>,
    #[account(
        init,
        payer=admin,
            associated_token::mint = mint,
            associated_token::authority = admin,
        )]
    pub user_ata: InterfaceAccount<'info, TokenAccount>,

    pub rent: Sysvar<'info, Rent>,
    pub system_program: Program<'info, System>,
    #[account(address = TOKEN_2022_ID)]
    pub token_program: Program<'info, Token2022>,
    /// CHECK: account constraint checked in account trait
    #[account(address = MPL_TOKEN_METADATA_ID)]
    pub token_metadata_program: UncheckedAccount<'info>,
    #[account(address = ASSOCIATED_TOKEN_ID)]
    pub associated_token_program: Program<'info, AssociatedToken>,
}

pub fn _initialize_metadata(
    ctx: Context<InitializeMetadata>,
    params: InitTokenParams,
) -> Result<()> {
    let admin_account = &ctx.accounts.admin;

    let seeds = &[MINT_SEED, &[ctx.bumps.mint]];
    let signer = [&seeds[..]];

    let meta_ix = CreateMetadataAccountV3Builder::new()
        .data(DataV2 {
            name: params.name.clone(),
            symbol: params.symbol.clone(),
            uri: params.uri,
            seller_fee_basis_points: 0,
            creators: None,
            collection: None,
            uses: None,
        })
        .is_mutable(true)
        .metadata(ctx.accounts.metadata.key())
        .mint(ctx.accounts.mint.key())
        .mint_authority(ctx.accounts.mint.key())
        .payer(admin_account.key())
        .rent(Some(ctx.accounts.rent.key()))
        .system_program(ctx.accounts.system_program.key())
        .update_authority(ctx.accounts.mint.key(), true)
        .instruction();

    invoke_signed(
        &meta_ix,
        &[
            ctx.accounts.metadata.to_account_info(),
            ctx.accounts.mint.to_account_info(),
            ctx.accounts.admin.to_account_info(),
            ctx.accounts.token_metadata_program.to_account_info(),
            ctx.accounts.token_program.to_account_info(),
            ctx.accounts.system_program.to_account_info(),
            ctx.accounts.rent.to_account_info(),
        ],
        &signer,
    )?;

    Ok(())
}

If it's any difference, my mint is already created and initialized, it also has token2022 extensions attached to it

This works however if the mint wasn't already created. Is there something I'm missing? how do I create a metadata?

samuelvanderwaal commented 5 months ago

The error you are running into is here. See the note above that says that these legacy handlers do not work for pNFTs or Token 2022 tokens; the latter seems to be your issue.

You will need to use one of the new Create handlers, for example this one. If your mint is already created you should set the as_signer to false for the mint.

The error message is a bit incomplete and should probably mention Token 2022 tokens as well. The error is here and that would be a nice simple PR you could make so someone else doesn't have to deal with the same confusion.

zikyfranky commented 5 months ago

Thanks for pointing me in the right direction, was just a misleading error message.

While I was waiting for a solution, I switched to the CreateV1Builder following this guide https://developers.metaplex.com/token-metadata/token-2022, however, I couldn't get it working as I needed an AccountInfo of the SysVar Instructions, I can see the Create handlers need this.

How do I get that? I tried adding it to my context, the same way Rent/Clock is added, but for some reason, Instructions lacks the SysVar trait, what other way can I specify the SysInstruction to Metaplex?

Sticking to UncheckedAccount.

samuelvanderwaal commented 5 months ago

Thanks for pointing me in the right direction, was just a misleading error message.

~While I was waiting for a solution, I switched to the CreateV1Builder following this guide https://developers.metaplex.com/token-metadata/token-2022, however, I couldn't get it working as I needed an AccountInfo of the SysVar Instructions, I can see the Create handlers need this.~

~How do I get that? I tried adding it to my context, the same way Rent/Clock is added, but for some reason, Instructions lacks the SysVar trait, what other way can I specify the SysInstruction to Metaplex?~

Sticking to UncheckedAccount.

You need to use an UncheckedAccount and then use the address constraint to assert that it's actually the Sysvar1nstructions1111111111111111111111111 address.

zikyfranky commented 5 months ago

Yeah, updated my comment.

PR has been created here, thanks again.