Marketplace has launched, further enabling blockchain developers! Learn more

How to Mint an NFT on Solana

September 23, 2022

Overview

Updated at: April 10, 2022

Welcome to another QuickNode guide on Solana - the up-and-coming blockchain that seeks to solve the scalability issues of Ethereum. We will be walking through step-by-step how to create an NFT on Solana. NFT, short for Non Fungible Token, is a cryptographically unique hash that is unreplicable. When you create an NFT, it is similar to creating an ERC20 token; however, the critical difference is only one token is ever issued. In this guide, we will be programmatically creating 2 separate accounts with wallets, one which will mint the NFT and another which will receive it. We will then be writing the code that will accomplish the minting and sending of the NFT on Solana. If you get stuck at any point, feel free to refer to the complete solution code at the end of the guide. Let us get to minting!

Prerequisites:
  •  NodeJS installed
  •  Terminal/CLI familiarity
  •  A Text editor
  •  TypeScript installed 

What is Solana?

Solana's goal is singular in nature. That goal is to scale the blockchain for global adoption. Solana Labs, the developers of the Solana Protocol, are doing a few different things to achieve that dream. 

Blockchain technology has a few knobs when it comes to tuning performance. One of which is the consensus mechanism. This is how nodes communicate together to arrive at an identical conclusion. Bitcoin uses Proof of Work or PoW. Binance Smart Chain, also known as BSC, uses a Proof of Staked Authority or PoSA. And Ethereum is migrating to Proof of Stake aka PoS. As you can tell, consensus is by no means a solved game at this point in time.

Solana uses a consensus called Proof of History. Proof of History works through a time-stamping solution; each transaction has a time stamp allocated to it that allows it to be verified as a legitimate transaction by the rest of the network in mere fractions of a second. Solana has a breakdown of the eight technologies that they believe position themselves as the fastest, most scalable, and most secure blockchain in the game.

Setting up the Project Locally

Open Terminal and navigate to a folder you'd like to create your project in. Next, run the following commands in this exact order:

setting up the project locally

Copy
mkdir SolanaNFT
npm install --prefix ./SolanaNFT @solana/web3.js @solana/spl-token
cd SolanaNFT
touch index.ts

The first command creates a new project directory called SolanaNFT. With npm install --prefix ./SolanaNFT @solana/web3.js @solana/spl-token, we're installing Solana's JavaScript API, @solana/web3.js and a TypeScript library @solana/spl-token, for interacting with the SPL Token program. Finally, with touch index.ts, we create a Typescript file, index.ts, where we'll be writing all of our code.

Connecting to Solana

Open the SolanaNFT project directory within your editor of choice, and let us start writing some code to connect to Solana!

Within the index.ts file, we'll want to start by importing all of the functionality we'll need from @solana/web3.js and @solana/spl-token. Add the following two import statements:

connecting to solana

Copy
import { clusterApiUrl, Connection, Keypair, LAMPORTS_PER_SOL } from  "@solana/web3.js";
import { createMint, getOrCreateAssociatedTokenAccount, mintTo, setAuthority, transfer } from  "@solana/spl-token";

> Note: If you are seeing errors from these lines of code, then you likely do not have the libraries installed. Ensure you're in the correct directory and install them again.  

Below the import statements, add this function: 

connecting to solana

Copy
(async () => {
// Connect to cluster
const connection = new Connection(clusterApiUrl('devnet'), "confirmed");
})

Here we are instantiating a new connection instance. This requires two arguments, the first being a URL endpoint that points to the Solana Network. In our case, clusterApiUrl('devnet') is a convenient method to point to the public endpoint of the Solana Devnet which is what we will be using in this tutorial. Solana has 3 different networks: the mainnet, the testnet, and the devnet. The devnet is a low-risk environment where you can "air drop" SOL tokens to yourself. 

With a connection established, we can now create the NFT and perform the other associated steps. 

> Note: Each of the code blocks we write going forward should be placed directly underneath the previous block, all within the curly braces of the top-level async function. We'll provide you with the full code at the end to check yours against. 

Creating a New Wallet and Airdropping SOL

The first task we'll need to accomplish is creating an account with a wallet and funding it. We'll also need to ensure that each step has completed successfully before moving on to the next. Here's what this code will look like:

creating a new wallet and airdropping sol

Copy
// Generate a new wallet keypair and airdrop SOL
const fromWallet = Keypair.generate();

const fromAirdropSignature = await connection.requestAirdrop(
  fromWallet.publicKey,
  LAMPORTS_PER_SOL
);

// Wait for airdrop confirmation
await connection.confirmTransaction(fromAirdropSignature);

Remember to add this code within the async function. Let us now break it down by line. 

Line 2: We're using the Keypair class we imported earlier to generate a new keypair by calling on a generate() method. This creates a new pair of a public and secret keys and stores it in fromWallet
 
Line 4: We're requesting an airdrop into our wallet. The requestAirdrop() method takes a public key and the amount of lamports in SOL you would like to receive. Lamports are Solana's equivalent to wei, the smallest amount that a SOL can be broken into. Most methods that require a number will default to the lamport measurement. In our case, the LAMPORTS\_PER\_SOL is a constant that represents 1 SOL worth of lamports. 

Line 9: To confirm that the airdrop has been successful, we're utilizing the confirmTransaction method and awaiting its success. This call allows us to pass in a signed transaction as an argument and have the program wait until it has been confirmed before moving on to other portions of the code. This is important as our next step will have to pay a fee, and we will require the airdropped funds.

Creating a New Token Mint

We'll now need to create a new token mint and retrieve our token account. 

creating a new token mint

Copy
const mint = await createMint(
  connection, 
  fromWallet,            // Payer of the transaction
  fromWallet.publicKey,  // Account that will control the minting 
  null,                  // Account that will control the freezing of the token 
  0                      // Location of the decimal place 
);

The createMint function will be what creates our actual token. It takes 6 arguments:
      1. The connection to the Solana Network. (connection)
      2. The account that will pay the fee. (fromWallet)
      3. The public key of the account that has the authority to mint tokens of this type. (fromWallet.publicKey)
      4. The public key of the account that has the authority to freeze tokens of this type. This argument is optional. (null)
      5. The location of the decimal place for the token. 

For more information on this function and other spl-token functions used in this guide, visit this page in Solana-labs.github.io.

Once the token mint is created, we need to grab the token account from the fromWallet Solana address. If it does not exist, we must create it. For this, we will utilize the getorCreateAssociatedTokenAccount() function, passing in most of the previous values, and storing it in fromTokenAccount

creating a new token mint

Copy
// Get the token account of the "fromWallet" Solana address. If it does not exist, create it.
const fromTokenAccount = await getOrCreateAssociatedTokenAccount(
  connection,
  fromWallet,
  mint,
  fromWallet.publicKey
);

You can think about the chain of custody like this: the NFT resides in the account, and your wallet owns this account. 
    
> Keys -> Wallet -> Account -> NFT (top to down)

Creating an Account with a Wallet to Send the NFT to

We have an account to send the NFT from; now, we need an account to send the NFT to. The code to achieve this should look very familiar as we'll be leveraging the same functions and variables to generate a new wallet and grab the token mint as we've done previously. 

creating an account with a wallet to send the nft to

Copy
// Generate a new wallet to receive the newly minted token
const toWallet = Keypair.generate();

// Get the token account of the "toWallet" Solana address. If it does not exist, create it.
const toTokenAccount = await mint.getOrCreateAssociatedAccountInfo(
  connection,
  fromWallet,
  mint,
  toWallet.publicKey
);

The above code block creates a wallet with a separate set of public/secret keys and then creates an account linking the mint variable to our newly created wallet.

Minting the NFT and Sending It

Now it's time to mint an NFT and send it to someone! Take a moment to look at the code below that achieves this and read the comments to understand what each function does. 

minting the nft and sending it

Copy
// Minting 1 new token to the "fromTokenAccount" account we just returned/created.
let signature = await mintTo(
  connection,
  fromWallet,               // Payer of the transaction fees 
  mint,                     // Mint for the account 
  fromTokenAccount.address, // Address of the account to mint to 
  fromWallet.publicKey,     // Minting authority
  1                         // Amount to mint 
);

await setAuthority(
  connection,
  fromWallet,            // Payer of the transaction fees
  mint,                  // Account 
  fromWallet.publicKey,  // Current authority 
  0,                     // Authority type: "0" represents Mint Tokens 
  null                   // Setting the new Authority to null
);

signature = await transfer(
  connection,
  fromWallet,               // Payer of the transaction fees 
  fromTokenAccount.address, // Source account 
  toTokenAccount.address,   // Destination account 
  fromWallet.publicKey,     // Owner of the source account 
  1                         // Number of tokens to transfer 
);

  
 console.log("SIGNATURE", signature);
})();


We'll briefly touch on the setAuthority() function as it is one of the most crucial parts. This function will revoke minting privileges and ensure that we can not create additional tokens of this type. Note that this action cannot be undone.

To execute the program, run the following commands one after another: 


minting the nft and sending it

Copy
tsc index.ts

node index.js

These two commands will run the TypeScript file, generate a JavaScript file with the same name, and run that file. You should see a signature logged in the terminal after some time.

If you visit the Solana Explorer, you should see your signature. It will look something like this:



Here's the complete code you should have: 

minting the nft and sending it

Copy
import { clusterApiUrl, Connection, Keypair, LAMPORTS_PER_SOL } from  "@solana/web3.js";
import { createMint, getOrCreateAssociatedTokenAccount, mintTo, setAuthority, transfer } from  "@solana/spl-token";

(async () => {
  // Connect to cluster
  const connection = new Connection(clusterApiUrl("devnet"), "confirmed");

  // Generate a new wallet keypair and airdrop SOL
  const fromWallet = Keypair.generate();
  const fromAirdropSignature = await connection.requestAirdrop(
    fromWallet.publicKey,
    LAMPORTS_PER_SOL
  );

  // Wait for airdrop confirmation
  await connection.confirmTransaction(fromAirdropSignature);

  // Create a new token 
  const mint = await createMint(
    connection, 
    fromWallet,            // Payer of the transaction
    fromWallet.publicKey,  // Account that will control the minting 
    null,                  // Account that will control the freezing of the token 
    0                      // Location of the decimal place 
  );

  // Get the token account of the fromWallet Solana address. If it does not exist, create it.
  const fromTokenAccount = await getOrCreateAssociatedTokenAccount(
    connection,
    fromWallet,
    mint,
    fromWallet.publicKey
  );

  // Generate a new wallet to receive the newly minted token
  const toWallet = Keypair.generate();

  // Get the token account of the toWallet Solana address. If it does not exist, create it.
  const toTokenAccount = await getOrCreateAssociatedTokenAccount(
    connection,
    fromWallet,
    mint,
    toWallet.publicKey
  );

  // Minting 1 new token to the "fromTokenAccount" account we just returned/created.
  let signature = await mintTo(
    connection,
    fromWallet,               // Payer of the transaction fees 
    mint,                     // Mint for the account 
    fromTokenAccount.address, // Address of the account to mint to 
    fromWallet.publicKey,     // Minting authority
    1                         // Amount to mint 
  );

  await setAuthority(
    connection,
    fromWallet,            // Payer of the transaction fees
    mint,                  // Account 
    fromWallet.publicKey,  // Current authority 
    0,                     // Authority type: "0" represents Mint Tokens 
    null                   // Setting the new Authority to null
  );

  signature = await transfer(
    connection,
    fromWallet,               // Payer of the transaction fees 
    fromTokenAccount.address, // Source account 
    toTokenAccount.address,   // Destination account 
    fromWallet.publicKey,     // Owner of the source account 
    1                         // Number of tokens to transfer 
  );

  console.log("SIGNATURE", signature);

})();

Conclusion

If you made it this far, you learned a few things from this tutorial and some from our other Solana guides, so congratulations! Having gone through this one, you have successfully created an NFT on the Solana blockchain. The next step for you to do would be to link this unique one-of-a-kind token, to some asset. In the market right now, it is typically a picture that has been randomly generated with various properties or a one-off piece of art. If you would like to learn how to do exactly that, you can learn how to do that in this tutorial!

Subscribe to our newsletter for more articles and guides on Ethereum. If you have any feedback, feel free to reach out to us via Twitter. You can always chat with us on our Discord community server, featuring some of the coolest developers you will ever meet :)

Related articles 33

Como crear un NFT en SOLANA
Published: Dec 27, 2021
Updated: Sep 23, 2022

¡Hola querido lector! Bienvenidos a una nueva guía de Solana.Solana es una blockchain que promete mucho a la hora de intentar resolver los problemas de escalabilidad que...

Continue reading
How to Get Transaction Logs on Solana
Published: Jun 24, 2022
Updated: Oct 27, 2022

Ever need to pull all the transactions associated with a Wallet? Want to see all of the mint transactions associated with a Candy Machine? Or maybe see transaction history of an NFT? Solana's...

Continue reading
How to Transfer SPL Tokens on Solana
Published: Sep 23, 2022
Updated: Sep 23, 2022

Sending Solana Program Library (SPL) Tokens is a critical mechanism for Solana development. Whether you are airdropping whitelist tokens to your community, bulk sending NFTs to another wallet,...

Continue reading
How to Send Bulk Transactions on Solana
Published: Aug 31, 2022
Updated: Oct 3, 2022

Are you running a batch process that has many transactions? Perhaps an airdrop to your community's NFT holders or a token distribution to early users of your dApp. Solana transaction...

Continue reading
Solana Fundamentals Reference Guide
Published: Oct 27, 2022
Updated: Oct 27, 2022

The Solana blockchain is a powerful tool, delivering thousands of transactions per second with almost no-cost transaction fees. If you are new to Web3 or have developed on EVM-based...

Continue reading