Gold Logo

NFT Minting Example

A comprehensive example of minting NFTs on Solana using the Gold Digger Factory Program.

Overview

This example demonstrates how to mint an NFT on the Solana blockchain using the Gold Digger Factory Program. The code handles the entire process from creating the mint account to setting up metadata and creating a master edition.

Key Features
  • Complete NFT minting process
  • Metaplex metadata integration
  • Royalty configuration
  • Error handling
  • Associated token account creation
NFT Metadata

The example uses a structured metadata format that follows the Metaplex standard. This includes basic information like name and symbol, as well as more advanced features like creators, royalties, and attributes.

Metadata Structure
{
  "name": "Gold Digger NFT #1",
  "symbol": "GOLD",
  "uri": "https://arweave.net/your-metadata-uri",
  "seller_fee_basis_points": 500,
  "creators": [
    {
      "address": "YOUR_WALLET_ADDRESS",
      "verified": true,
      "share": 100
    }
  ],
  "collection": {
    "name": "Gold Digger Collection",
    "family": "Gold Digger",
    "verified": true
  },
  "attributes": [
    {
      "trait_type": "Rarity",
      "value": "Legendary"
    },
    {
      "trait_type": "Mining Power",
      "value": "100"
    }
  ],
  "external_url": "https://golddigger.io"
}
Minting Process
The NFT minting process involves several steps and interactions with different Solana programs

Step-by-Step Process

  1. Create Mint Account

    First, we create a new account that will represent our NFT mint. This account will store the mint data.

  2. Initialize Mint

    We initialize the mint with the SPL Token program, setting the mint authority and freeze authority.

  3. Create Associated Token Account

    We create an associated token account for the owner to hold the NFT.

  4. Mint Token

    We mint exactly one token to the associated token account.

  5. Create Metadata

    We create a metadata account using the Metaplex Token Metadata program.

  6. Create Master Edition

    Finally, we create a master edition account that makes the token non-fungible.

NFT Minting Process Diagram

Visual representation of the NFT minting process

Code Example
Complete Rust code example for minting an NFT on Solana
use solana_client::rpc_client::RpcClient;
use solana_program::{
    pubkey::Pubkey,
    system_instruction,
};
use solana_sdk::{
    commitment_config::CommitmentConfig,
    signature::{Keypair, read_keypair_file},
    signer::Signer,
    transaction::Transaction,
};
use spl_token::{
    instruction as token_instruction,
    state::{Mint, Account},
};
use spl_associated_token_account::{
    get_associated_token_address,
    instruction::create_associated_token_account,
};
use metaplex_token_metadata::{
    instruction::{create_metadata_accounts_v3, create_master_edition_v3},
    state::{DataV2, Creator, Collection, Uses, UseMethod},
};

// Main NFT minting function
pub async fn mint_nft(
    rpc_url: &str,
    payer_keypair_path: &str,
    metadata: &NFTMetadata,
    is_mutable: bool,
) -> Result<String, MintError> {
    // Connect to Solana cluster
    let client = RpcClient::new_with_commitment(
        rpc_url.to_string(),
        CommitmentConfig::confirmed(),
    );
    
    // Load the payer's keypair from file
    let payer = match read_keypair_file(payer_keypair_path) {
        Ok(keypair) => keypair,
        Err(_) => return Err(MintError::WalletError("Failed to read keypair file".to_string())),
    };
    
    // Generate a new keypair for the NFT mint
    let mint_keypair = Keypair::new();
    
    // Get the associated token account for the payer
    let associated_token_account = get_associated_token_address(
        &payer.pubkey(),
        &mint_keypair.pubkey(),
    );
    
    // Create all the necessary instructions
    let instructions = vec![
        // Create mint account
        system_instruction::create_account(
            &payer.pubkey(),
            &mint_keypair.pubkey(),
            client.get_minimum_balance_for_rent_exemption(Mint::LEN).unwrap(),
            Mint::LEN as u64,
            &spl_token::ID,
        ),
        
        // Initialize mint
        token_instruction::initialize_mint(
            &spl_token::ID,
            &mint_keypair.pubkey(),
            &payer.pubkey(),
            Some(&payer.pubkey()),
            0,
        ).unwrap(),
        
        // Create associated token account
        create_associated_token_account(
            &payer.pubkey(),
            &payer.pubkey(),
            &mint_keypair.pubkey(),
        ),
        
        // Mint one token to the associated token account
        token_instruction::mint_to(
            &spl_token::ID,
            &mint_keypair.pubkey(),
            &associated_token_account,
            &payer.pubkey(),
            &[&payer.pubkey()],
            1,
        ).unwrap(),
        
        // Create metadata account
        create_metadata_accounts_v3(
            metaplex_token_metadata::ID,
            metadata_account,
            mint_keypair.pubkey(),
            payer.pubkey(),
            payer.pubkey(),
            payer.pubkey(),
            metadata.name.clone(),
            metadata.symbol.clone(),
            metadata.uri.clone(),
            creators.clone(),
            metadata.seller_fee_basis_points,
            true,
            is_mutable,
            None,
            None,
            None,
        ),
        
        // Create master edition (makes the NFT non-fungible)
        create_master_edition_v3(
            metaplex_token_metadata::ID,
            master_edition,
            mint_keypair.pubkey(),
            payer.pubkey(),
            payer.pubkey(),
            metadata_account,
            payer.pubkey(),
            Some(0), // Max supply of 0 means the NFT cannot be duplicated
        ),
    ];
    
    // Create and sign the transaction
    let recent_blockhash = match client.get_latest_blockhash() {
        Ok(hash) => hash,
        Err(e) => return Err(MintError::TransactionError(format!("Failed to get blockhash: {}", e))),
    };
    
    let transaction = Transaction::new_signed_with_payer(
        &instructions,
        Some(&payer.pubkey()),
        &[&payer, &mint_keypair],
        recent_blockhash,
    );
    
    // Send and confirm the transaction
    match client.send_and_confirm_transaction(&transaction) {
        Ok(signature) => {
            println!("✅ NFT created successfully!");
            println!("Transaction signature: {}", signature);
            
            Ok(signature.to_string())
        },
        Err(e) => Err(MintError::TransactionError(format!("Transaction failed: {}", e))),
    }
}
Error Handling
Proper error handling is crucial for robust NFT minting applications

The example includes a comprehensive error handling system using custom error types. This makes it easier to identify and debug issues during the minting process.

#[derive(Error, Debug)]
pub enum MintError {
    #[error("Failed to connect to Solana: {0}")]
    ConnectionError(String),
    
    #[error("Invalid wallet data: {0}")]
    WalletError(String),
    
    #[error("Transaction error: {0}")]
    TransactionError(String),
    
    #[error("Metadata error: {0}")]
    MetadataError(String),
    
    #[error("Token error: {0}")]
    TokenError(String),
    
    #[error("IO error: {0}")]
    IoError(String),
}

Each error type provides specific information about what went wrong, making it easier to troubleshoot issues. The error messages are designed to be user-friendly while still providing enough technical detail for debugging.