Creating compressed NFTs using Solana bubblegum v2 - mintV2 function implementation

I’m working on creating compressed NFTs on Solana using metaplex tools. I want to use the newer bubblegum v2 library to mint cNFTs within a Merkle tree structure. My goal is to mint an NFT directly into a collection using the mintV2 function.

I wrote this code that uploads metadata and attempts to mint the compressed NFT:

import {mintV2} from '@metaplex-foundation/mpl-bubblegum';
import {some, none} from '@metaplex-foundation/umi';
import loadConfigPath from './loadConfigPath.mjs';
import setupUmi from './setupUmi.mjs';
import uploadAsset from './uploadAsset.mjs';
import uploadMetadata from './uploadMetadata.mjs';
import loadKeypairFromFile from './loadKeypairFromFile.mjs';
import ACCOUNT_ADDRESS from './ACCOUNT_ADDRESS.mjs';

const nftData = {
    "name": "Sample NFT",
    "description": "Testing compressed NFT creation",
    "category": "Digital Art",
}

console.log('Starting image upload process...');
const imageUrl = await uploadAsset(
    loadConfigPath('artwork.png'),
    'image/png'
);
console.log('Image upload complete! URI:', imageUrl);

const metadataObject = {
    name: nftData.name,
    image: imageUrl,
    description: nftData.description,
    external_url: 'https://example.com',
    attributes: [
        {
            trait_type: 'Category',
            value: nftData.category,
        },
    ],
    properties: {
        files: [
            {
                uri: imageUrl,
                type: 'image/png',
            },
        ],
    },
};

console.log('Metadata object:', JSON.stringify(metadataObject));
console.log('Uploading metadata to storage...');
const metadataUrl = await uploadMetadata(metadataObject);
console.log('Metadata upload successful! URI:', metadataUrl);

const collectionKeypair = await loadKeypairFromFile('collection-keypair.bin');
const treeKeypair = await loadKeypairFromFile('tree-keypair.bin');

const mintTransaction = await mintV2(setupUmi, {
    leafOwner: setupUmi.identity.publicKey,
    merkleTree: treeKeypair.publicKey,
    metadata: {
        name: nftData.name,
        uri: metadataUrl,
        collection: none(),
        sellerFeeBasisPoints: 250,
        creators: [
            {
                address: setupUmi.identity.publicKey,
                verified: true,
                share: 100,
            },
        ],
    },
}).sendAndConfirm(setupUmi);

console.log('Transaction result:', JSON.stringify(mintTransaction));
const {signature} = mintTransaction;
console.log('Transaction signature:', signature);

The code executes without errors but I don’t see the NFT in my Phantom wallet on devnet. How can I verify if the compressed NFT was actually created and determine its account address?

Hey! Are you passing setupUmi correctly to mintV2? I see you’re doing mintV2(setupUmi, {...}) but I’m wondering if setupUmi is actually returning the configured umi instance.

What’s up with your tree initialization? Did you create and configure the merkle tree beforehand with the right parameters? The mint can succeed but if the tree wasn’t set up with proper depth/buffer size it’ll cause issues.

One thing caught my eye - you’re using collection: none() in your metadata. Are you intentionally minting outside a collection or do you want it in that collection you loaded the keypair for? If you want it in the collection, use some({ key: collectionKeypair.publicKey, verified: false }) instead.

Have you tried using a DAS API endpoint to query your wallet address? The Helius or QuickNode DAS API should show your cNFTs even if Phantom doesn’t. What does your tree keypair address look like when you log it? Might help us debug.

cnfts dont show in phantom without extra steps. try checkin solana explorer or use helus das api to look for the mint. first check your tx signature on solscan to see if it minted right.

Yeah, this is super common with compressed NFTs. Regular NFTs show up in Phantom automatically, but cNFTs don’t have individual blockchain accounts so they won’t appear in standard wallet interfaces.

Your code looks fine, but check a few things. First - did you properly initialize your Merkle tree before minting? You’ll need createTree from the bubblegum library if you skipped that step.

To verify the mint actually worked, check your transaction signature on Solana Explorer. Look for program logs from the Bubblegum program.

For viewing your cNFT, you’ll need the Digital Asset Standard API to query compressed assets by owner. Use the getAssetsByOwner RPC endpoint - it’ll return your compressed NFTs. Some newer wallets are starting to support cNFTs natively, but most still need custom DAS API integration.