How To Mint NFTs on Solana Using Rust and Metaplex

In this how-to, you’ll learn how to mint an NFT on Solana by writing a Rust smart contract and using Metaplex’s Token Metadata Program

Anoushk
Better Programming

--

solana nfts

Welcome readers. This is the start of a new series of blog posts about Solana development, and in this one, you’ll learn how to write a custom contract to mint your NFT in only four steps.

Some General Tips About Solana Development

In Solana development, you’ll face a lot of weird custom errors and bugs, and it can be quite hard and frustrating to fix them since the Solana dev ecosystem is not as big as the Eth dev ecosystem. But not to worry. When you get stuck you simply have to look in the right place for the solution.

During my development, I was constantly asking my doubts in the Anchor discord server, the Metaplex and Superteam server, and looking through other code repos on GitHub and the Metaplex Program library itself.

Project Overview

The tools we’ll be using for this:

Getting Started

Prep work

Use the CLI to set your network to devnet with the following command:

solana config set --url devnet

To confirm if it worked, check the output after entering the cmd:

Config File: /Users/anoushkkharangate/.config/solana/cli/config.yml
RPC URL: https://api.devnet.solana.com
WebSocket URL: wss://api.devnet.solana.com/ (computed)
Keypair Path: /Users/anoushkkharangate/.config/solana/id.json
Commitment: confirmed

Next, if you haven’t already, set up a file system wallet using this guide, Solana wallet docs, and also add some devnet sol using the command solana airdrop 1

Lastly, use anchor CLI to make an anchor project with this command:

anchor init <name-of-your-project>

Make sure that Anchor.toml is also set to devnet.

That’s it now. You are all set to eat glass!

Step 1. Import the Dependencies

In your project, there must be a folder called programs. Go to programs/<your-project-name>/Cargo.toml, and add these dependencies. Make sure to use version 0.24.2 and you can use avm to change it

[dependencies]
anchor-lang = "0.24.2"
anchor-spl = "0.24.2"
mpl-token-metadata = {version = "1.2.7", features = ["no-entrypoint"]}

Anchor has pulled down all versions before 0.24.2 due to a security vulnerability hence make sure to use this exact one

Then go to the lib.rs file in src and import these:

use anchor_lang::prelude::*;
use anchor_lang::solana_program::program::invoke;
use anchor_spl::token;
use anchor_spl::token::{MintTo, Token};
use mpl_token_metadata::instruction::{create_master_edition_v3, create_metadata_accounts_v2};

Cool. Now we can write the mint function!

Step 2. Writing the Mint Function Struct

First, let’s create the accounts struct for the mint function

Don’t worry about the Unchecked accounts, as we will pass these into the Metaplex program which will check them for us.

In order to use Unchecked accounts in Anchor, you need to add this comment above each account:

/// CHECK: This is not dangerous because we don't read or write from this account

Step 3. The Mint Function 🪙

Let’s make a function that uses the struct we just made to mint the token:

If you want debug your program, better use msg!() to log whatever value you want to check. It accepts string so you’ll have to use std::string::ToString to convert. Your logs will appear in the terminal or in .anchor/program-logs/<program-id>

logs path

So, a Few Things Here…

The creator array needs to have the person minting the NFTs as part of it, but you can set the share as 0, so it doesn’t really matter. Here’s the code:

I haven’t implemented Collections, as it’s not in the scope of this guide but you can do it by using:

mpl_token_metadata::instruction::set_and_verify_collection

Regarding why I’ve set Max supply to 0 here. In Metaplex, if the token is meant to be one of a kind, then you have to set its max supply to zero since total supply — supply claimed (1–1) equals 0

Once you’ve written the function run anchor build && anchor deploy and you should see the deployed Program ID

deployed program id in terminal

paste this program ID in your Anchor.toml and the lib.rs file wherever you see this default ID Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS

Step 4. Calling the Mint Function

Before doing anything, make sure that you have imported @solana/web3.js and @solana/spl-token. Inside tests/<test-file>.ts add these imports and constants:

Now let's make the token and the associated token account, as shown below:

Note: the mint and freeze authority has to be same otherwise it doesn’t work.

createInitializeMintInstruction( mintKey.publicKey, 0, program.provider.wallet.publicKey,// mint auth program.provider.wallet.publicKey // freeze auth
),

Now, call the mint function and pass all the data and accounts

That’s it! Now just run the anchor test, and you should be able to mint your NFT.

Account:  4swRFMNovHCkXY3gDgAGBXZwpfFuVyxWpWsgXqbYvoZG1M63nZHxyPRm7KTqAjSdTpHn2ivyPr6jQfxeLsB6a1nX
Mint key: DehGx61vZPYNaMWm9KYdP91UYXXLu1XKoc2CCu3NZFNb
User: 7CtWnYdTNBb3P9eViqSZKUekjcKnMcaasSMC7NbTVKuE
Metadata address: 7ut8YMzGqZAXvRDro8jLKkPnUccdeQxsfzNv1hjzc3Bo
MasterEdition: Au76v2ZDnWSLj23TCu9NRVEYWrbVUq6DAGNnCuALaN6o
Your transaction signature KwEst87H3dZ5GwQ5CDL1JtiRKwcXJKNzyvQShaTLiGxz4HQGsDA7EW6rrhqwbJ2TqQFRWzZFvhfBU1CpyYH7WhH
✔ Is initialized! (6950ms)
1 passing (7s)✨ Done in 9.22s.

If you get any custom program error with a hex value like 0x1, convert the hex value to plain text, then go to metaplex github and search using your browser for the number + 1 th appearance of the word “error(“

You can check out the NFT here:

Wrapping Up

I hope this guide was useful for all the Solana geeks out there. When I first tried to mint an NFT, I was pulling my hair out, but it slowly started to make sense once some fellow glass eaters explained it to me. Hopefully, I’ve made it that much easier for you.

Here’s the GitHub for this project:

You can follow me on my Twitter and Github. Until next time, keep eating glass!

Big thanks to Pratik Saria and 0xDeep for helping me understand how Solana NFTs and Anchor works. If it weren’t for them, I’d still be trying to figure it out.

--

--

engineering @tinydancerio - a light client on @solana • member @SuperteamDao • rust