BigBlocks Docs
Components/Inscriptions

CollectionMintButton

Create NFT collections with metadata, traits, rarities, and royalty configurations

Create comprehensive NFT collections with metadata, traits, rarities, and royalty configurations. Collections are parent inscriptions that define the structure and attributes for collection items.

Demo

Art CollectionDigital art collection with multiple traits and rarities
Gaming CollectionCharacter cards with class and element traits
Music CollectionLimited edition music tracks with artist royalties
Custom CollectionCreate your own collection with custom configuration

Collection Creation Features:

Cover Image UploadMulti-Step WizardRarity ConfigurationTrait SystemRoyalty ManagementValidation & Preview

Demo Note: This demonstrates NFT collection creation with a 5-step wizard: Basic Info → Rarities → Traits → Royalties → Review. Cover images must be square (max 1MB, 2048x2048px). Royalties are capped at 7% total per 1sat standard.

API Reference

This component extends the Button and Dialog primitives from Radix and uses DropZone for cover image upload and StepIndicator for the guided creation process.

Installation

npx bigblocks add collection-mint-button

Import

import { CollectionMintButton } from 'bigblocks';

Props

PropTypeRequiredDefaultDescription
collectionPartial<CollectionData>No-Pre-filled collection data
buttonTextstringNo"Create Collection"Button text
dialogTitlestringNo"Create NFT Collection"Dialog title
variant'solid' | 'soft' | 'outline' | 'ghost'No'solid'Button variant
size'1' | '2' | '3' | '4'No'2'Button size
color'blue' | 'green' | 'red' | 'gray'No'blue'Button color
classNamestringNo-Custom CSS classes
disabledbooleanNofalseWhether button is disabled
onSuccess(txid: string, collection: CollectionData) => voidNo-Success callback with transaction ID
onError(error: Error) => voidNo-Error callback

Types

CollectionData

interface CollectionData {
  // Basic info
  name: string;
  description: string;
  quantity?: number;
  // Cover image
  coverImage: File | null;
  // Rarities
  rarities: CollectionRarity[];
  // Traits
  traits: CollectionTraits;
  // Royalties
  royalties: CollectionRoyalty[];
}

CollectionRarity

interface CollectionRarity {
  label: string;
  percentage: string; // Decimal format: "0.5000" = 50%
  items?: string; // Number of items with this rarity
}

CollectionRoyalty

interface CollectionRoyalty {
  type: RoytaltyType;
  destination: string;
  percentage: string; // Decimal format: "0.0100" = 1%
}

Basic Usage

import { CollectionMintButton } from 'bigblocks';

export default function CollectionCreator() {
  const handleSuccess = (txid: string, collection: CollectionData) => {
    console.log('Collection created!', { txid, collection });
    // Redirect to collection management
    router.push(`/collections/${txid}`);
  };

  const handleError = (error: Error) => {
    console.error('Collection creation failed:', error);
    // Show error message to user
  };

  return (
    <div className="p-6">
      <h2>Create Your NFT Collection</h2>
      <CollectionMintButton
        onSuccess={handleSuccess}
        onError={handleError}
      />
    </div>
  );
}

Advanced Usage

Pre-configured Collection

import { CollectionMintButton } from 'bigblocks';

export default function GameCollections() {
  const gameCollectionDefaults = {
    name: 'Hero Cards',
    description: 'Collectible hero cards for the fantasy game',
    quantity: 10000,
    rarities: [
      { label: 'Common', percentage: '0.6000' },
      { label: 'Rare', percentage: '0.3000' },
      { label: 'Epic', percentage: '0.0900' },
      { label: 'Legendary', percentage: '0.0100' }
    ],
    traits: {
      'Class': {
        values: {
          'Warrior': { rarity: '0.2500' },
          'Mage': { rarity: '0.2500' },
          'Archer': { rarity: '0.2500' },
          'Assassin': { rarity: '0.2500' }
        }
      },
      'Element': {
        values: {
          'Fire': { rarity: '0.2000' },
          'Water': { rarity: '0.2000' },
          'Earth': { rarity: '0.2000' },
          'Air': { rarity: '0.2000' },
          'Light': { rarity: '0.1000' },
          'Dark': { rarity: '0.1000' }
        }
      }
    }
  };

  return (
    <CollectionMintButton
      collection={gameCollectionDefaults}
      buttonText="Create Game Collection"
      dialogTitle="Deploy Hero Card Collection"
      color="green"
      onSuccess={(txid, collection) => {
        // Save to game database
        saveGameCollection({ txid, ...collection });
        
        // Set up minting pipeline
        initializeCollectionMinting(txid);
      }}
    />
  );
}

Marketplace Integration

import { CollectionMintButton } from 'bigblocks';
import { useState } from 'react';

export default function MarketplaceCollections() {
  const [collections, setCollections] = useState([]);

  const handleCollectionCreation = (txid: string, collection: CollectionData) => {
    setCollections(prev => [...prev, { txid, ...collection }]);
    
    // Auto-setup marketplace listing
    createMarketplaceCollection({
      collectionTxid: txid,
      name: collection.name,
      description: collection.description,
      floorPrice: 1000, // sats
      royalties: collection.royalties
    });
  };

  return (
    <div className="space-y-6">
      <CollectionMintButton
        onSuccess={handleCollectionCreation}
        buttonText="Launch New Collection"
      />
      
      {collections.length > 0 && (
        <div>
          <h3>Your Collections</h3>
          <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
            {collections.map(collection => (
              <div key={collection.txid} className="border rounded-lg p-4">
                <h4 className="font-semibold">{collection.name}</h4>
                <p className="text-sm text-gray-600">{collection.description}</p>
                <div className="mt-2 flex justify-between">
                  <span className="text-xs">Items: {collection.quantity}</span>
                  <span className="text-xs">Traits: {Object.keys(collection.traits).length}</span>
                </div>
              </div>
            ))}
          </div>
        </div>
      )}
    </div>
  );
}

Collection Creation Steps

The component guides users through a 5-step process:

1. Basic Information

  • Collection name and description
  • Quantity (optional for unlimited)
  • Cover image upload (square, max 1MB, max 2048x2048px)

2. Rarity Configuration

  • Define rarity tiers with labels and percentages
  • Percentage or item count modes
  • Automatic percentage validation (must sum to 100%)

3. Trait Definition

  • Create trait categories (e.g., "Background", "Eyes", "Accessories")
  • Define trait values with individual rarity percentages
  • Support for multiple traits per category

4. Royalty Setup

  • Configure creator royalties (max 7% per 1sat standard)
  • Support for multiple royalty recipients
  • Automatic validation of royalty totals

5. Review & Deploy

  • Complete collection preview
  • Estimated deployment cost
  • Final validation before blockchain deployment

Cover Image Requirements

Image Validation

  • Format: PNG, JPEG, GIF, or WebP
  • Size: Maximum 1MB file size
  • Dimensions: Must be square (same width and height)
  • Maximum Resolution: 2048x2048 pixels

Best Practices

// Example image preparation
const prepareCollectionImage = async (file: File): Promise<boolean> => {
  // Validate format
  const validTypes = ['image/png', 'image/jpeg', 'image/gif', 'image/webp'];
  if (!validTypes.includes(file.type)) {
    throw new Error('Invalid image format');
  }
  
  // Check size limit
  if (file.size > 1024 * 1024) {
    throw new Error('Image too large (max 1MB)');
  }
  
  // Validate dimensions
  return new Promise((resolve, reject) => {
    const img = new Image();
    img.onload = () => {
      if (img.width !== img.height) {
        reject(new Error('Image must be square'));
      } else if (img.width > 2048) {
        reject(new Error('Image too large (max 2048x2048)'));
      } else {
        resolve(true);
      }
    };
    img.src = URL.createObjectURL(file);
  });
};

Trait System

Trait Categories

// Example trait structure
const artCollectionTraits = {
  'Background': {
    values: {
      'Solid Blue': { rarity: '0.3000' },    // 30%
      'Gradient': { rarity: '0.2000' },      // 20%
      'Abstract': { rarity: '0.1500' },      // 15%
      'Cosmic': { rarity: '0.0500' }         // 5%
    }
  },
  'Style': {
    values: {
      'Minimalist': { rarity: '0.4000' },    // 40%
      'Detailed': { rarity: '0.3000' },      // 30%
      'Experimental': { rarity: '0.2000' },  // 20%
      'Surreal': { rarity: '0.1000' }        // 10%
    }
  }
};

Rarity Calculation

// Calculate overall item rarity
const calculateItemRarity = (traits: Record<string, string>) => {
  let totalRarity = 1;
  
  Object.entries(traits).forEach(([category, value]) => {
    const traitRarity = parseFloat(
      collectionTraits[category]?.values[value]?.rarity || '1'
    );
    totalRarity *= traitRarity;
  });
  
  return totalRarity;
};

Royalty Management

Royalty Configuration

// Example royalty setup
const royaltyConfig = [
  {
    type: RoytaltyType.PAYMAIL,
    destination: 'artist@handcash.io',
    percentage: '0.0500' // 5%
  },
  {
    type: RoytaltyType.ADDRESS,
    destination: '1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa',
    percentage: '0.0200' // 2%
  }
];

Royalty Validation

  • Maximum 7% total royalties per 1sat standard
  • Minimum 0.01% per recipient
  • Automatic percentage validation
  • Support for paymail and Bitcoin addresses

Error Handling

Common error scenarios:

  • Invalid image format/size
  • Rarity percentages don't sum to 100%
  • Royalty percentages exceed 7%
  • Trait configuration errors
  • Wallet connectivity issues
const handleError = (error: Error) => {
  switch (error.message) {
    case 'Royalties exceed maximum 7%':
      setErrorMessage('Total royalties cannot exceed 7%. Please adjust your royalty configuration.');
      break;
    case 'Rarities must sum to 100%':
      setErrorMessage('Rarity percentages must total 100%. Please check your rarity configuration.');
      break;
    default:
      setErrorMessage(`Collection creation failed: ${error.message}`);
  }
};

Integration Examples

Social Media Integration

const handleCollectionCreation = (txid: string, collection: CollectionData) => {
  // Share collection launch
  const message = `🎨 Just launched "${collection.name}" NFT collection on Bitcoin SV! ${collection.quantity} items with ${Object.keys(collection.traits).length} trait categories.`;
  
  socialPost({
    message,
    attachments: [{ type: 'collection', txid }],
    hashtags: ['#NFT', '#BSV', '#Collection']
  });
};

Analytics Integration

const trackCollectionMetrics = (collection: CollectionData) => {
  analytics.track('Collection Created', {
    name: collection.name,
    quantity: collection.quantity,
    traitCount: Object.keys(collection.traits).length,
    rarityTiers: collection.rarities.length,
    royaltyRecipients: collection.royalties.length
  });
};

Best Practices

Collection Planning

// Plan your collection structure
const planCollection = {
  // Clear theme and concept
  name: 'Pixel Warriors',
  description: '8-bit style warrior characters for the metaverse',
  
  // Reasonable quantity
  quantity: 5000, // Not too large for initial launch
  
  // Balanced rarities
  rarities: [
    { label: 'Common', percentage: '0.5000' },     // 50%
    { label: 'Uncommon', percentage: '0.3000' },   // 30%
    { label: 'Rare', percentage: '0.1500' },       // 15%
    { label: 'Epic', percentage: '0.0450' },       // 4.5%
    { label: 'Legendary', percentage: '0.0050' }    // 0.5%
  ]
};

Trait Design

  • Keep trait categories meaningful and distinct
  • Balance common vs rare traits
  • Consider trait interaction and combination possibilities
  • Plan for future trait additions

Royalty Strategy

// Sustainable royalty structure
const sustainableRoyalties = [
  {
    type: RoytaltyType.PAYMAIL,
    destination: 'creator@domain.com',
    percentage: '0.0300' // 3% - reasonable for creator
  },
  {
    type: RoytaltyType.ADDRESS,
    destination: 'platform-address',
    percentage: '0.0150' // 1.5% - platform fee
  }
  // Total: 4.5% - leaves room for secondary market growth
];