Minting a tree for compressed NFTs

apollotoday

Nick

Posted on March 23, 2023

Minting a tree for compressed NFTs

If you are still NFT Twitter adjacent, you've seen a firehouse of tweets about compressed NFTs. Just like with Candy Machine V1, they are all the rage. Today we are focused on step one of minting a compressed NFT, minting a tree on-chain.

I've found a few great explanations on what compressed NFTs are:

Compression

Alchemy's: What are compressed NFTs?

Metaplex's: Expanding Digital Assets with Compression for NFTs

The main goal of compressed NFTs is to dramatically decrease the cost of minting to greatly widen the adoption of Solana NFTs.

When working with toy Solana projects, I've found that using a Next.js app is the best way to get started quickly. In my experience, you need a node server to work with Metaplex code. With the api folder, you can get a lot done without having to worry about compatibility and code splitting.

Getting started

We need to install relevant dependencies

npm install @solana/spl-account-compression @solana/web3.js @metaplex-foundation/mpl-bubblegum @mintee/wrapped-connection
Enter fullscreen mode Exit fullscreen mode

The first part of working with compressed NFTs is familiarizing yourself with the connection wrapper. If you follow any example, you will see that it extends the normal @solana/web3.js Connection class with some helpers around Keypairs and compressed NFTs. You pass in your RPC URL and a keypair to sign/pay for transactions.

import WrappedConnection from "@mintee/wrapped-connection"
import {
  Keypair,
  PublicKey,
  SystemProgram,
  Transaction,
  sendAndConfirmTransaction,
} from "@solana/web3.js";


const keypair = new Keypair()
const connectionWrapper = WrappedConnection.getConnectionWrapper("https://api.mainnet-beta.solana.com", keypair);
Enter fullscreen mode Exit fullscreen mode

We are going to define a function called mintTree(). When minting an account to hold your tree, you need to define the depth and buffer size. 2^{DEPTH} is the capacity of the tree.

When working with Solana, you have to calculate how large the account size needs to be upfront. When working with compressed NFTs, you have a higher up-front cost, but each mint is cheaper.

How do they work?

export async function mintTree() {
  const payer = connectionWrapper.payer.publicKey;
  const treeKeypair = new Keypair();


  const maxDepth = 14
  const maxBufferSize = 64

// create account size based on number of NFTs
  const space = getConcurrentMerkleTreeAccountSize(maxDepth, maxBufferSize);
// get tree authority 
  const [treeAuthority, _bump] = await PublicKey.findProgramAddressSync(
    [treeKeypair.publicKey.toBuffer()],
    BUBBLEGUM_PROGRAM_ID
  );
Enter fullscreen mode Exit fullscreen mode

Now that we have created the instructions for minting an account we need to write the transactions for allocating the account and creating the tree.

const createTreeIx = createCreateTreeInstruction(
    {
      merkleTree: treeKeypair.publicKey,
      treeAuthority,
      treeCreator: payer,
      payer,
      logWrapper: SPL_NOOP_PROGRAM_ID,
      compressionProgram: SPL_ACCOUNT_COMPRESSION_PROGRAM_ID,
    },
    {
      maxBufferSize,
      maxDepth,
      public: false,
    },
    BUBBLEGUM_PROGRAM_ID
  );


  let tx = new Transaction().add(allocTreeIx).add(createTreeIx);
  tx.feePayer = payer;
Enter fullscreen mode Exit fullscreen mode

After sending the transaction we will get back an assetId. The assetId is a PDA of Bubblegum. It the equivalent of a token address. This is where compressed NFTs get controversial. They are a pretty unique RPC extension, so if you mint a compressed NFT on Helius per se, you have to use that RPC to get back the info.

try {
    await sendAndConfirmTransaction(
      connectionWrapper,
      tx,
      [treeKeypair, connectionWrapper.payer],
      {
        commitment: "confirmed",
        skipPreflight: true,
      }
    );

    console.log(
      "Successfull created merkle tree for account: " + treeKeypair.publicKey
    );

    return treeKeypair.publicKey;


  } catch (e) {
    console.error("Failed to create merkle tree: ", e);
    throw e;
  }
}
Enter fullscreen mode Exit fullscreen mode
💖 💪 🙅 🚩
apollotoday
Nick

Posted on March 23, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related