How to Mint Solana Compressed NFTs (cNFTs) with TypeScript

kishi.sol
6 min readSep 18, 2023

--

gm! This is kishi.sol from ELSOUL LABO and Epics DAO.

The Solana chain is relatively inexpensive by default, but even so, minting a single NFT costs 0.012 SOL (about $0.24, calculated at 1 SOL = $20). This scales linearly, so a 10,000-piece NFT collection would cost $2,400, and creating 10 billion NFTs would require $240 million (!!!), which is not realistic.

When considering game development, there is a need to reduce this financial cost as all items and player profiles are turned into NFTs, a form of digital asset.

That’s where the development of Compressed NFT (cNFT) comes in. Just last week, Magic Eden made it possible to buy and sell cNFTs, making it a technology to watch.

With cNFT, you can issue a 10,000-piece NFT collection for about $70 (34 times cheaper), and even 10 billion pieces for about $10,000 (24,000 times cheaper), making it a realistic cost for issuing NFT collections.

Although it’s a very excellent technology, it’s still under active development, so the information is scattered.

For busy people, I’ve summarized the information you’ll need to mint and use Solana Compressed NFTs with TypeScript.

What You Need to Mint Solana Compressed NFT (cNFT)

Solana Compressed NFT (cNFT) is an NFT that is efficiently managed using data structures like Merkle Trees to reduce data volume while ensuring authenticity, taking a different approach from regular NFTs.

You’ll need a Solana RPC endpoint that supports the Read API feature.

Our DAO uses Helius.

This time, we’ll use TypeScript to mint cNFTs, and the following tools and documentation will be helpful.

How to Mint cNFT

For those who want to see the code first, let’s go from here:

The minting procedure consists of the following three steps:

  1. Creating the NFT collection (createNFTCollection.ts)
  2. Creating the Merkle Tree (createMerkleTree.ts)
  3. Minting the cNFT (mintCNFT.ts)

Let’s actually mint a cNFT by moving our hands. If you use Skeet, you can quickly prepare the environment for Solana development, including cNFTs.

$ npm i -g @skeet-framework/cli
$ skeet create your-app-name

Please select the Solana Mobile Stack. The environment installation will begin.

First, set up the .env file.

NODE_ENV=development
SOLANA_MAINNET_RPC_URL=https://rpc.helius.xyz/?api-key=
SOLANA_DEVNET_RPC_URL=https://devnet.helius-rpc.com/?api-key=
WALLET_FILE=./key.json
# See: nft.storage/docs/quickstart/#get-an-api-token
NFT_STORAGE_KEY=

This time, we’ll use Helius for RPC and Nft Storage for storage.
Both can be used for free right away.

If you have a wallet created with the Solana CLI, you can use it.

Also, if you have a wallet created with Phantom, there is a script to convert it to json, so please use it.
Run the following command, and you’ll be prompted to enter the string you can get from Phantom’s Show Private Key. Please copy and paste it and hit Enter.

$ yarn solana:key:convert (default: key.json)
// If you want to specify the name of the key
$ yarn solana:key:convert -- keyfile.json

`your-app-name/scripts/solana/cNFT/config.ts`

import { publicKey } from '@metaplex-foundation/umi'
import { format } from 'date-fns'

export const COLLECTION_NAME = 'Skeet The Epics Dev'
export const COLLECTION_SYMBOL = 'STED'
export const COLLECTION_DESCRIPTION =
'Epics using Skeet. Welcome early adoptooooooooooooors!'
export const FEE_PERCENT = 5.5
export const EXTERNAL_URL = 'https://skeet.dev/'
export const COLLECTION_IMAGE_PATH = 'scripts/solana/cNFT/example/TheDev.png'
export const CREATORS = [
{
address: publicKey('YLmoXgFkKFT6V6FumUPgBJXBJ9gAPPoYtacMfoTUPpy'),
verified: false,
share: 40,
},
{
address: publicKey('DcLN5EYHBSexnKdipnSmiFAKevcxGijURonzaWfri8Cq'),
verified: false,
share: 30,
},
{
address: publicKey('DfCHMeHfRYMBQwMje5bLSqimMWXhArYoTomX2vRr6Ty9'),
verified: false,
share: 30,
},
]
// You will obtain this after creating the NFT collection in Step 1.
export const COLLECTION_MINT = publicKey(
'itzdT5XgD9cLRtFSTbLAeEqKM3aT3UeSTCJ5h1A9cNN'
)
// You will obtain this after creating the Merkle Tree in Step 2.
export const MERKLE_TREE = publicKey(
'AqWn6rLoJJvexv9Eyu6MiYyAjzptJqMRTiMnopjRW38Q'
)

export const MINT_ITEM_TO = publicKey(
'ELLBGa6DTdEVui6Ydt8vqsnsyybAxyVLPwY7oH6onbUq'
)
export const NFT_ITEM_NAME = 'STED Limited Edition #0'
export const NFT_ITEM_IMAGE_URL =
'https://bafkreihwkrj3su3r6mz5wvmu46h5iriomh2b6njwd3m2s3f6whwd3qxude.ipfs.nftstorage.link/'
export const NFT_ITEM_ATTRIBUTES = [
{
trait_type: 'Status',
value: 'Early adaptooooooooooors',
},
{
trait_type: 'Minted',
value: format(new Date(), 'yyyy-MM-dd HH:mm:ss'),
},
]

// To get cNFTs, for now we can't use umi
export const OWNER_ADDRESS = 'ELLBGa6DTdEVui6Ydt8vqsnsyybAxyVLPwY7oH6onbUq'
export const COLLECTION_MINT_ADDRESS =
'itzdT5XgD9cLRtFSTbLAeEqKM3aT3UeSTCJ5h1A9cNN'

Please replace the config and images as appropriate.

COLLECTION_MINT can be obtained in step 1, and MERKLE_TREE can be obtained in step 2.

  1. Creating the NFT Collection (createNFTCollection.ts)

After changing the images and settings (it’s okay if you don’t change them), run the following command.

$ yarn solana:nft:create:collection

The necessary addresses will be output to the console and the example folder.
Replace the string inside the publicKey of COLLECTION_MINT in config.ts with the collectionMint address you get here.

2. Creating the Merkle Tree (createMerkleTree.ts)

After correctly replacing COLLECTION_MINT, create the Merkle Tree.

The command is:

$ yarn solana:nft:create:merkleTree

Again, replace the string inside the publicKey of MERKLE_TREE in config.ts with the merkleTree address you get here.

3. Minting the cNFT (mintCNFT.ts)

After correctly replacing the MERKLE_TREE string, please set the NFT_ITEM_IMAGE_URL (you can use the URL you get in step 1 to create an item with the same image as the collection. You can also change the item image by uploading a separate image to nft.storage).

MINT_ITEM_TO is the address to which the cNFT will be minted.

NFT_ITEM_ATTRIBUTES is

type Attribute = {
trait_type: string,
value: string
}

and you can add multiple items.

After confirming various settings, you can mint with the following command:

$ yarn solana:nft:mint:cnft

You can check the transaction of the Compressed NFT as nftItemMint:

Checking the Data of the Minted cNFT

You should be able to confirm the minted cNFT on your Phantom wallet as well.

Here, let’s also check the Node.js script for retrieving cNFT data.

Retrieving cNFT Data (getCNFT.ts)

From config.ts’s OWNER_ADDRESS and COLLECTION_MINT_ADDRESS, you can use the ReadAPI to retrieve assets owned by that owner (OWNER_ADDRESS) and assets included in the NFT collection (COLLECTION_MINT_ADDRESS).

You can run this script with the following command.

$ yarn solana:nft:get:cnft

You can view each code here. (GitHub)

Skeet Document is here:

This time, I summarized how to Mint Solana Compressed NFT (cNFT).

If you have any questions, please feel free to leave a comment.

Next, I want to write about how to actually incorporate this Compressed NFT into the app.

See you again!

LFGGGGG

--

--

kishi.sol

Software Researcher. Co-founder of Epics DAO and ELSOUL LABO. Contributor to Solana Labs. Creator of BDLC NFT and Skeet Serverless Framework. NFA DYOR