What is the simplest way to create an NFT using Anchor, without using the candy machine.
The goal is to be able to mint a token and corresponding metadata. Ideally with a single instruction.
What is the simplest way to create an NFT using Anchor, without using the candy machine.
The goal is to be able to mint a token and corresponding metadata. Ideally with a single instruction.
This seems to be a common question and I can see why there is confusion on the subject. This is an open request on the Anchor project as of this writing.
First, it is important to understand what an NFT on Solana actually is. It is a somewhat complex relationship between a number of accounts. The best place to look would be the Candy Machine program itself.
At minimum, we're usually talking about the following:
Optionally, there are other things like collections and editions. But these are not necessary to see the NFT displayed properly on marketplaces.
It is important to understand that anyone can extend an NFT with their own custom program by using a PDA address derived from tokens governed by the Mint.
With that out of the way, you'd create a Mint and Token account from Anchor, the usual way. One easy way would be to use the accounts context to define a Mint and have Anchor initialize it.
Example:
#[derive(Accounts)]
pub struct MintNFT<'info> {
#[account(
init,
payer = payer,
mint::decimals = 0,
mint::authority = mint_authority,
seeds = [MINT_PREFIX.as_bytes(), your_pda_path_goes_here ], bump
)]
pub mint: Account<'info, Mint>,
#[account(
init,
payer = payer,
associated_token::mint = mint,
associated_token::authority = mint_authority,
)]
pub token: Account<'info, TokenAccount>,
#[account(mut)]
pub metadata: AccountInfo<'info>,
#[account(mut)]
pub master_edition: AccountInfo<'info>,
...
}
The dots above would include things like the required signers, the payer, the token program, the metaplex program, among other things.
Then, inside the instruction handler, you'd invoke a mint_to instruction to give the token account 1 token.
Once the token has been "minted", you'd need to do a cross-program-invoke (CPI) to ask the metaplex program to initialize the metadata.
Here is an example of that call:
let metadata_infos = vec![
ctx.accounts.metadata.clone(),
ctx.accounts.mint.clone(),
ctx.accounts.mint_authority.to_account_info().clone(),
ctx.accounts.mint_authority.to_account_info().clone(),
ctx.accounts.token_metadata_program.clone(),
ctx.accounts.token_program.to_account_info().clone(),
ctx.accounts.system_program.to_account_info().clone(),
ctx.accounts.rent.to_account_info().clone(),
nft_machine.to_account_info().clone(),
];
/* set the metadata of the NFT */
invoke_signed(
&create_metadata_accounts(
*ctx.accounts.token_metadata_program.key,
*ctx.accounts.metadata.key,
*ctx.accounts.mint.key,
*ctx.accounts.mint_authority.key,
*ctx.accounts.mint_authority.key,
nft_machine.key(),
nft_name,
nft_machine.data.symbol.to_string(),
nft_uri,
Some(creators),
nft_machine.data.seller_fee_basis_points,
true,
false,
),
metadata_infos.as_slice(),
&[&authority_seeds],
)?;
You can see this in action in the following:
Further information can be found here:
https://docs.metaplex.com/architecture/basic_flow#creating-a-token-metadata-account
You don't need to write any Anchor to create an NFT.
In Ethereum, you might be familiar with ERC-721, which defines an interface for NFT implementers to follow. Solana doesn't work like that.
On Solana, an NFT is just a token created with the regular token program with supply 1 and a frozen mint. The picture and name and the other stuff you'd associate with an NFT is handled by the Metaplex token standard, for which there is also an on-chain program.
So you don't need to deploy any new Anchor code. All you need to do to mint an NFT is 1) create a mint 2) mint 1 token 3) freeze the mint, and 4) set the Metaplex NFT data for the token. And you can do that all from the javascript SDK.