originbyte

docs/nft-protocol/minting/mintcap

MintCap

A MintCap is an object that serves to guarantee minting authority over a certain type.

For each type T created for a Collection there is a corresponding type MintCap<T>. It stands for Mint Capability, and it is the object that gives its owner the ability to mint NFTs from its type.

/// `MintCap<T>` delegates the capability of it's owner to mint `T`
struct MintCap<phantom T> has key, store {
    /// `MintCap` ID
    id: UID,
    /// ID of the `Collection` that `MintCap` controls.
    ///
    /// Intended for discovery.
    collection_id: ID,
    /// Supply that `MintCap` can mint
    supply: Option<Supply>,
}

/// `Supply` tracks supply parameters
///
/// `Supply` can be frozen, therefore making it impossible to change the
/// maximum supply.
struct Supply has store, drop {
    frozen: bool,
    max: u64,
    current: u64,
}

Limited vs. unlimited supply

A MintCap<T> can either mint an unlimited number of NFTs of type T, or a limited amount. This is defined by its supply field. When mint_cap.supply is None the supply is unlimited; Some means it is limited.

Creating MintCaps

There are essentially two ways to create a MintCap from scratch: from a DelegatedWitness or via the Publisher object.

In the first scenario, acquire DelegatedWitness<T> and call mint_cap::new(). Alternatively, create the MintCap together with the collection by calling collection::create_with_mint_cap().

Usually this step is done in the init function of the contract, but it can also be done later in a transaction.

Fungibility

Two mint cap objects of the same type T are fungible. Split with mint_cap::split(), merge with mint_cap::merge().

Minting function

The minting function must exist in the contract the creator deploys — OriginByte does not export a generic mint. Only the contract that defines a type can generate objects of that type. The purpose of MintCap is to be used in your mint function interface.

When minting NFTs with limited supply, take &mut MintCap<T>:

public entry fun mint_avatar(
    name: String,
    color: String,
    mood: String,
    url: vector<u8>,
    // Need to be mut because supply is limited at 10_000 Avatars
    mint_cap: &mut MintCap<Avatar>,
    warehouse: &mut Warehouse<Avatar>,
    ctx: &mut TxContext,
) {
    let nft = Avatar {
        id: object::new(ctx),
        name,
        url: url::new_unsafe_from_bytes(url),
        color,
        mood,
    };

    mint_event::mint_limited(mint_cap, &nft);
    warehouse::deposit_nft(warehouse, nft);
}

When minting with unlimited supply, &MintCap<T> is enough:

public entry fun mint_hat(
    type: String,
    // Does not need to be mut because supply is unlimited
    mint_cap: &MintCap<Hat>,
    warehouse: &mut Warehouse<Hat>,
    ctx: &mut TxContext,
) {
    let nft = Hat {
        id: object::new(ctx),
        type,
    };

    mint_event::mint_unlimited(mint_cap, &nft);
    warehouse::deposit_nft(warehouse, nft);
}