Features
Minting
So far, we’ve learned how to create and maintain Candy Machines. We’ve seen how to configure them and how to set up complex minting workflows using guard and guard groups. It’s about time we talk about the last piece of the puzzle: Minting!
Basic Minting
As mentioned in the Candy Guards page, there are two programs responsible for minting NFTs from Candy Machines: The Candy Machine Core program — responsible for minting the NFT — and the Candy Guard program which adds a configurable Access Control layer on top of it and can be forked to offer custom guards.
As such, there are two ways to mint from a Candy Machine:
From a Candy Guard program which will then delegate the minting to the Candy Machine Core program. Most of the time, you will want to do this as it allows for much more complex minting workflows. You may need to pass extra remaining accounts and instruction data to the mint instruction based on the guards configured in the account. Fortunately, our SDKs make this easy by requiring a few extra parameters and computing the rest for us.
Directly from the Candy Machine Core program. In this case, only the configured mint authority can mint from it and, therefore, it will need to sign the transaction.
If everything went well, an NFT will be created following the parameters configured in the Candy Machine. For instance, if the given Candy Machine uses Config Line Settings with Is Sequential set to false
, then we will get the next item at random.
Starting from version 1.0
of the Candy Guard program, The mint instruction accepts an additional minter
signer which can be different than the existing payer
signer. This allows us to create minting workflows where the wallet that mints the NFT is no longer requires to pay SOL fees — such as storage fees and SOL mint payments — as the payer
signer will abstract away those fees. Note that the minter
signer will still need to pay for token-based fees and will be used to validate the configured guards.
Please note that the latest mint instruction relies on the latest Token Metadata instructions which use a fair amount of compute units. As such, you may need to increase the compute unit limit of the transaction to ensure it is successful. Our SDKs may also help with this.
Mint from a Candy Machine
To mint from a Candy Machine via a configured Candy Guard account, you may use the mintV2
function and provide the mint address and update authority of the collection NFT the minted NFT will belong to. A minter
signer and payer
signer may also be provided but they will default to Umi's identity and payer respectively.
As mentioned above, you may need to increase the compute unit limit of the transaction to ensure the mintV2
instruction is successful. You may do this by using the setComputeUnitLimit
helper function on the mpl-toolbox
Umi library as illustrated in the code snippet below.
If you want to mint pNFT (e.g. for royalty enforcement) and have your Candy Machine set up accordingly you will have to add the tokenStandard
field. By default NonFungible
is used. If you fetched the Candy Machine before you could use candyMachine.tokenStandard
, otherwise you have to assign it yourself by using tokenStandard: TokenStandard.ProgrammableNonFungible
from @metaplex-foundation/mpl-token-metadata
.
import { mintV2 } from '@metaplex-foundation/mpl-candy-machine'
import { setComputeUnitLimit } from '@metaplex-foundation/mpl-toolbox'
import { transactionBuilder, generateSigner } from '@metaplex-foundation/umi'
const nftMint = generateSigner(umi)
await transactionBuilder()
.add(setComputeUnitLimit(umi, { units: 800_000 }))
.add(
mintV2(umi, {
candyMachine: candyMachine.publicKey,
nftMint,
collectionMint: collectionNft.publicKey,
collectionUpdateAuthority: collectionNft.metadata.updateAuthority,
tokenStandard: candyMachine.tokenStandard,
})
)
.sendAndConfirm(umi)
Note that the mintV2
instruction takes care of creating the Mint and Token accounts for us by default and will set the NFT owner to the minter
. If you wish to create these yourself beforehand, you may simply give the NFT mind address as a public key instead of a signer. Here's an example using the createMintWithAssociatedToken
function from the mpl-toolbox
Umi library:
import { mintV2 } from '@metaplex-foundation/mpl-candy-machine'
import {
createMintWithAssociatedToken,
setComputeUnitLimit,
} from '@metaplex-foundation/mpl-toolbox'
import { transactionBuilder, generateSigner } from '@metaplex-foundation/umi'
const nftMint = generateSigner(umi)
const nftOwner = generateSigner(umi).publicKey
await transactionBuilder()
.add(setComputeUnitLimit(umi, { units: 800_000 }))
.add(createMintWithAssociatedToken(umi, { mint: nftMint, owner: nftOwner }))
.add(
mintV2(umi, {
candyMachine: candyMachine.publicKey,
nftMint: nftMint.publicKey,
collectionMint: collectionNft.publicKey,
collectionUpdateAuthority: collectionNft.metadata.updateAuthority,
})
)
.sendAndConfirm(umi)
In the rare event that you wish to mint directly from the Candy Machine Core program, you may use the mintFromCandyMachineV2
function instead. This function requires the mint authority of the candy machine to be provided as a signer and accepts an explicit nftOwner
attribute.
import { mintFromCandyMachineV2 } from '@metaplex-foundation/mpl-candy-machine'
import { setComputeUnitLimit } from '@metaplex-foundation/mpl-toolbox'
import { transactionBuilder, generateSigner } from '@metaplex-foundation/umi'
const nftMint = generateSigner(umi)
const nftOwner = generateSigner(umi).publicKey
await transactionBuilder()
.add(setComputeUnitLimit(umi, { units: 800_000 }))
.add(
mintFromCandyMachineV2(umi, {
candyMachine: candyMachine.publicKey,
mintAuthority: umi.identity,
nftOwner,
nftMint,
collectionMint: collectionNft.publicKey,
collectionUpdateAuthority: collectionNft.metadata.updateAuthority,
})
)
.sendAndConfirm(umi)
API References: mintV2, mintFromCandyMachineV2
Minting With Guards
When minting from a Candy Machine that uses a bunch of guards, you may need to provide additional guard-specific information.
If you were to build the mint instruction manually, that information would be provided as a mixture of instruction data and remaining accounts. However, using our SDKs, each guard that requires additional information at mint time defines a set of settings that we call Mint Settings. These Mint Settings will then be parsed into whatever the program needs.
A good example of a guard that requires Mint Settings is the NFT Payment guard which requires the mint address of the NFT we should use to pay for the mint amongst other things.
Each available guard contains its own documentation page and it will tell you whether or not that guard expects Mint Settings to be provided when minting.
If you were to only use guards that do not require Mint Settings, you may mint in the same way described by the “Basic Minting” section above. Otherwise, you’ll need to provide an additional object attribute containing the Mint Settings of all guards that require them. Let’s have a look at what that looks like in practice using our SDKs.
Mint from a Candy Machine with guards
When minting via the Umi library, you may use the mintArgs
attribute to provide the required Mint Settings.
Here’s an example using the Third Party Signer guard which requires an additional signer and the Mint Limit guard which keeps track of how many times a wallet minted from the Candy Machine.
import {
some,
generateSigner,
transactionBuilder,
} from '@metaplex-foundation/umi'
import { create, mintV2 } from '@metaplex-foundation/mpl-candy-machine'
import { setComputeUnitLimit } from '@metaplex-foundation/mpl-toolbox'
// Create a Candy Machine with guards.
const thirdPartySigner = generateSigner()
await create(umi, {
// ...
guards: {
thirdPartySigner: some({ signer: thirdPartySigner.publicKey }),
mintLimit: some({ id: 1, limit: 3 }),
},
}).sendAndConfirm(umi)
// Mint from the Candy Machine.
const nftMint = generateSigner(umi)
await transactionBuilder()
.add(setComputeUnitLimit(umi, { units: 800_000 }))
.add(
mintV2(umi, {
candyMachine: candyMachine.publicKey,
nftMint,
collectionMint: collectionNft.publicKey,
collectionUpdateAuthority: collectionNft.metadata.updateAuthority,
mintArgs: {
thirdPartySigner: some({ signer: thirdPartySigner }),
mintLimit: some({ id: 1 }),
},
})
)
.sendAndConfirm(umi)
API References: mintV2, DefaultGuardSetMintArgs
Minting With Guard Groups
When minting from a Candy Machine using guard groups, we must explicitly select which group we want to mint from by providing its label.
Additionally, Mint Settings may also be required as explained in the previous section. However, the Mint Settings will apply to the “Resolved Guards” of the selected group.
For instance, imagine a Candy Machine with the following guards:
- Default Guards:
- Bot Tax
- Third Party Signer
- Start Date
- Group 1
- Label: “nft”
- Guards:
- NFT Payment
- Start Date
- Group 2
- Label: “public”
- Guards:
- Sol Payment
The Resolved Guards of Group 1 — labelled “nft” — are:
- Bot Tax: from the Default Guards.
- Third Party Signer: from the Default Guards.
- NFT Payment: from Group 1.
- Start Date: from Group 1 because it overrides the default guard.
Therefore, the provided Mint Settings must be related to these Resolved Guards. In the example above, Mint Settings must be provided for the Third Party Signer guard and the NFT Payment guard.
Mint from a Candy Machine with guard groups
When minting from a Candy Machine using guard groups, the label of the group we want to select must be provided via the group
attribute.
Additionally, the Mint Settings for the Resolved Guards of that group may be provided via the mintArgs
attribute.
Here is how we would use the Umi library to mint from the example Candy Machine described above.
// Create a Candy Machine with guards.
const thirdPartySigner = generateSigner()
await create(umi, {
// ...
guards: {
botTax: some({ lamports: sol(0.001), lastInstruction: true }),
thirdPartySigner: some({ signer: thirdPartySigner.publicKey }),
startDate: some({ date: dateTime('2022-10-18T17:00:00Z') }),
},
groups: [
{
label: 'nft',
guards: {
nftPayment: some({ requiredCollection, destination: nftTreasury }),
startDate: some({ date: dateTime('2022-10-18T16:00:00Z') }),
},
},
{
label: 'public',
guards: {
solPayment: some({ lamports: sol(1), destination: solTreasury }),
},
},
],
}).sendAndConfirm(umi)
// Mint from the Candy Machine.
const nftMint = generateSigner(umi)
await transactionBuilder()
.add(setComputeUnitLimit(umi, { units: 800_000 }))
.add(
mintV2(umi, {
candyMachine: candyMachine.publicKey,
nftMint,
collectionMint: collectionNft.publicKey,
collectionUpdateAuthority: collectionNft.metadata.updateAuthority,
group: some('nft'),
mintArgs: {
thirdPartySigner: some({ signer: thirdPartySigner }),
nftPayment: some({
mint: nftFromRequiredCollection.publicKey,
destination: nftTreasury,
tokenStandard: TokenStandard.NonFungible,
}),
},
})
)
.sendAndConfirm(umi)
API References: mintV2, DefaultGuardSetMintArgs
Minting With Pre-Validation
It is important to note that some guards may require additional verification steps before we can mint from their Candy Machine. This pre-validation step usually creates an account on the blockchain or rewards the wallet with a token that acts as proof of that verification.
Using the route instruction
One way guards can require a pre-validation step is by using their own special instruction via the “route” instruction.
A good example of that is the Allow List guard. When using this guard, we must verify that our wallet belongs to a predefined list of wallets by calling the route instruction and providing a valid Merkle Proof. If this route instruction is successful, it will create an Allow List PDA for that wallet which the mint instruction can then read to validate the Allow List guard. You can read more about the Allow List guard on its dedicated page.
Using external services
Another way guards may perform that pre-validation step is by relying on an external solution.
For instance, when using the Gatekeeper guard, we must request a Gateway Token by performing a challenge — such as completing a Captcha — which depends on the configured Gatekeeper Network. The Gatekeeper guard will then check for the existence of such Gateway Token to either validate or reject the mint. You can learn more about the Gatekeeper guard on its dedicated page.
Minting With Bot Taxes
One guard you’ll likely want to include in your Candy Machine is the Box Tax guard which protects your Candy Machine against bots by charging failed mints a configurable amount of SOL. This amount is usually small to hurt bots without affecting genuine mistakes from real users. All bot taxes will be transferred to the Candy Machine account so that, once minting is over, you can access these funds by deleting the Candy Machine account.
This guard is a bit special and affects the minting behaviour of all other guards. When the Bot Tax is activated and any other guard fails to validate the mint, the transaction will pretend to succeed. This means no errors will be returned by the program but no NFT will be minted either. This is because the transaction must succeed for the funds to be transferred from the bot to the Candy Machine account. You can learn more about the Bot Tax guard on its dedicated page.
Conclusion
Congratulations, you now know how Candy Machines work from A to Z!
Here are some additional reading resources you might be interested in:
- All Available Guards: Have a look through all the guards available to you so you can cherry-pick the ones you need.
- Create Your First Candy Machine (coming soon): This How-To guide helps you upload your assets and create a new Candy Machine from scratch using a CLI tool called “Sugar”. It also uses our JS SDK to spin up a minting website for your Candy Machine.