From 5c18ba0a4b5956af606ce6b6126d584529351b7e Mon Sep 17 00:00:00 2001 From: L0STE <125566964+L0STE@users.noreply.github.com> Date: Thu, 12 Dec 2024 20:17:54 +0100 Subject: [PATCH 1/6] Refactoring Overview & Structure --- .../products/coreCandyMachine/index.js | 141 ++---------- .../getting-started/index.md | 151 ++++++++++++- src/pages/core-candy-machine/index.md | 21 +- src/pages/core-candy-machine/overview.md | 210 ------------------ 4 files changed, 177 insertions(+), 346 deletions(-) delete mode 100644 src/pages/core-candy-machine/overview.md diff --git a/src/components/products/coreCandyMachine/index.js b/src/components/products/coreCandyMachine/index.js index dc9c6d24..e0b26638 100644 --- a/src/components/products/coreCandyMachine/index.js +++ b/src/components/products/coreCandyMachine/index.js @@ -32,42 +32,21 @@ export const coreCandyMachine = { ], }, { - title: 'Core Candy Machine', + title: 'Actions', links: [ - { - title: 'Overview', - href: '/core-candy-machine/overview', - }, - { title: 'Candy Guards', href: '/core-candy-machine/guards' }, - { - title: 'Preparing Assets', - href: '/core-candy-machine/preparing-assets', - }, { title: 'Creating a Candy Machine', href: '/core-candy-machine/create', }, { - title: 'Inserting Items', + title: 'Loading Items in a Candy Machine', href: '/core-candy-machine/insert-items', }, { title: 'Updating a Candy Machine and Guards', href: '/core-candy-machine/update', }, - { - title: 'Guard Groups and Phases', - href: '/core-candy-machine/guard-groups', - }, - { - title: 'Special Guard Instructions', - href: '/core-candy-machine/guard-route', - }, - { - title: 'Fetching a Candy Machine', - href: '/core-candy-machine/fetching-a-candy-machine', - }, { title: 'Minting from a Candy Machine', href: '/core-candy-machine/mint', @@ -76,119 +55,31 @@ export const coreCandyMachine = { title: 'Withdrawing a Candy Machine', href: '/core-candy-machine/withdrawing-a-candy-machine', }, + { + title: 'Fetching a Candy Machine', + href: '/core-candy-machine/fetching-a-candy-machine', + }, ], }, { - title: 'Available Guards', + title: 'Candy Guards', + links: [ { - title: 'Address Gate', - href: '/core-candy-machine/guards/address-gate', - }, - { - title: 'Allocation', - href: '/core-candy-machine/guards/allocation', - }, - { - title: 'Allow List', - href: '/core-candy-machine/guards/allow-list', - }, - { - title: 'Asset Burn', - href: '/core-candy-machine/guards/asset-burn', - }, - { - title: 'Asset Burn Multi', - href: '/core-candy-machine/guards/asset-burn-multi', - }, - { - title: 'Asset Gate', - href: '/core-candy-machine/guards/asset-gate', - }, - { - title: 'Asset Payment', - href: '/core-candy-machine/guards/asset-payment', - }, - { - title: 'Asset Payment Multi', - href: '/core-candy-machine/guards/asset-payment-multi', - }, - { - title: 'Asset Mint Limit', - href: '/core-candy-machine/guards/asset-mint-limit', - }, - { title: 'Bot Tax', href: '/core-candy-machine/guards/bot-tax' }, - { title: 'End Date', href: '/core-candy-machine/guards/end-date' }, - { title: 'Edition', href: '/core-candy-machine/guards/edition' }, - { - title: 'Freeze Sol Payment', - href: '/core-candy-machine/guards/freeze-sol-payment', - }, - { - title: 'Freeze Token Payment', - href: '/core-candy-machine/guards/freeze-token-payment', - }, - { - title: 'Gatekeeper', - href: '/core-candy-machine/guards/gatekeeper', - }, - { - title: 'Mint Limit', - href: '/core-candy-machine/guards/mint-limit', - }, - { title: 'NFT Burn', href: '/core-candy-machine/guards/nft-burn' }, - { title: 'NFT Gate', href: '/core-candy-machine/guards/nft-gate' }, - { - title: 'NFT Mint Limit', - href: '/core-candy-machine/guards/nft-mint-limit', - }, - { - title: 'NFT Payment', - href: '/core-candy-machine/guards/nft-payment', - }, - { - title: 'Program Gate', - href: '/core-candy-machine/guards/program-gate', - }, - { - title: 'Redeemed Amount', - href: '/core-candy-machine/guards/redeemed-amount', - }, - { - title: 'Sol Fixed Fee', - href: '/core-candy-machine/guards/sol-fixed-fee', - }, - { - title: 'Sol Payment', - href: '/core-candy-machine/guards/sol-payment', - }, - { - title: 'Start Date', - href: '/core-candy-machine/guards/start-date', - }, - { - title: 'Third Party Signer', - href: '/core-candy-machine/guards/third-party-signer', - }, - { - title: 'Token Burn', - href: '/core-candy-machine/guards/token-burn', - }, - { - title: 'Token Gate', - href: '/core-candy-machine/guards/token-gate', + title: 'Overview', + href: '/core-candy-machine/guards/candy-guard-overview', }, { - title: 'Token Payment', - href: '/core-candy-machine/guards/token-payment', + title: 'Candy Groups and Phases', + href: '/core-candy-machine/guards/candy-guard-overview', }, { - title: 'Token2022 Payment', - href: '/core-candy-machine/guards/token2022-payment', + title: 'Custom Guards', + href: '/core-candy-machine/guards/candy-guard-overview', }, { - title: 'Vanity Mint', - href: '/core-candy-machine/guards/vanity-mint', + title: 'Available Candy Guards', + href: '/core-candy-machine/guards/candy-guard-overview', }, ], }, diff --git a/src/pages/core-candy-machine/getting-started/index.md b/src/pages/core-candy-machine/getting-started/index.md index 0169da75..123fcc8a 100644 --- a/src/pages/core-candy-machine/getting-started/index.md +++ b/src/pages/core-candy-machine/getting-started/index.md @@ -4,15 +4,162 @@ metaTitle: Getting Started | Core Candy Machine description: The starting point in getting to know the Core Candy Machine program and packages. --- -Select the language / library you want to use below to get started with Core Candy Machines. +Choose your preferred language or library below to get started or learn more about how Candy Machine works. {% .lead %} {% quick-links %} {% quick-link title="JavaScript" icon="JavaScript" href="/core-candy-machine/getting-started/js" description="Get started with our JavaScript library based on the Umi framework." /%} -{% quick-link title="Rust" icon="Rust" href="/core-candy-machine/getting-started/rust" description="Get started using our Rust crate." /%} +{% quick-link title="Rust" icon="Rust" href="/core-candy-machine/getting-started/rust" description="Get started with our Rust crate." /%} {% /quick-links %} +## Candy Machine 101 + +Candy Machine have 4 different phases: +- [Creating and Configuring a Candy Machine](#create-and-configure) +- [Loading all the Assets](#load-items) +- [Minting the Assets](#mint-asset) +- [Deleting and Withdraw the Candy Machine](#delete-and-withdraw) + +{% diagram %} +{% node #action-1 label="1. Create & Configure" theme="pink" /%} +{% node #action-2 label="2. Insert Items" parent="action-1" y="50" theme="pink" /%} + +{% node parent="action-1" x="250" %} +{% node #candy-machine label="Candy Machine" theme="blue" /%} +{% node label="Settings" /%} +{% node #item-1 label="Item 1" /%} +{% node #item-2 label="Item 2" /%} +{% node #item-3 label="Item 3" /%} +{% node #item-rest label="..." /%} +{% /node %} + +{% node parent="candy-machine" x="180" y="20" %} +{% node #mint label="3. Mint" theme="pink" /%} +{% node #mint-1 label="Mint #1" theme="pink" /%} +{% node #mint-2 label="Mint #2" theme="pink" /%} +{% node #mint-3 label="Mint #3" theme="pink" /%} +{% /node %} + +{% node #nft-1 parent="mint" x="120" label="Asset" theme="blue" /%} +{% node #nft-2 parent="nft-1" y="50" label="Asset" theme="blue" /%} +{% node #nft-3 parent="nft-2" y="50" label="Asset" theme="blue" /%} + +{% edge from="action-1" to="candy-machine" path="straight" /%} +{% edge from="action-2" to="item-1" /%} +{% edge from="action-2" to="item-2" /%} +{% edge from="action-2" to="item-3" /%} +{% edge from="action-2" to="item-rest" /%} +{% edge from="item-1" to="mint-1" /%} +{% edge from="item-2" to="mint-2" /%} +{% edge from="item-3" to="mint-3" /%} +{% edge from="mint-1" to="nft-1" path="bezier" /%} +{% edge from="mint-2" to="nft-2" path="bezier" /%} +{% edge from="mint-3" to="nft-3" path="bezier" /%} +{% /diagram %} + +### Create and Configure + +Start by creating a new Core Candy Machine and configuring it with custom settings. This includes defining a collection that will be assigned to all NFTs created by the Candy Machine and all the customization that natively comes by adding [Candy Guards]() to the Candy Machine. + +**Note**: Candy Guards are modular code that adds custom behavior to the Candy Machine. + +Learn more about [How to create a Candy Machine]() + +### Load Items + +A newly created Candy Machine can't mint NFTs until it’s loaded with the assets to be minted. + +Each item to load includes: +- `name`: The name of the Asset. +- `uri`: The URI pointing to the [JSON schema](/core/json-schema) of the Asset that has already been uploaded via either an onchain (e.g. Arweave, IPFS) or off-chain (e.g. AWS, your own server) storage provider. + +**Note**: If you're not familiar with how to upload metadata, you can follow [this paragraph](/core/guides/javascript/how-to-create-a-core-nft-asset-with-javascript#creating-the-metadata-for-the-asset) or use Sugar! + +Learn more about [How to load a Candy Machine]() + +### Mint Asset + +Once all items are loaded into the Candy Machine and pre-configured conditions are met, users can begin minting assets. + +**Note**: To let the user easily access a way to mint from the candy machine, we've created this guide: [Create a Website for minting Assets from your Core Candy Machine](/guides/create-a-core-candy-machine-ui) + +Learn more about [How to Mint from a Candy Machine]() + +### Delete and Withdraw + +After the Candy Machine has fulfilled its purpose, it can be safely deleted to reclaim the rent paid for storing its data on-chain. + +Learn more about [How to Delete a Candy Machine]() + +----todo + +## Candy Guards + +Now that we understand how Core Candy Machines work, let’s dig into the various ways creators can protect and customize the mint process of their Core Candy Machine. + +Creators can use what we call “**Guards**” to add various features to their Core Candy Machine. The Metaplex Core Candy Machine ships with an additional Solana Program called **Candy Guard** that ships with [**a total of 23 default guards**](/core-candy-machine/guards). By using an additional program, it allows advanced developers to fork the default Candy Guard program to create their own custom guards whilst still being able to rely on the main Candy Machine program. + +Each guard can be enabled and configured at will so creators can pick and choose the features they need. Disabling all guards would be equivalent to allowing anyone to mint our NFTs for free at any time, which is likely not what we want. So let’s have a look at a few guards to create a more realistic example. + +Say a Core Candy Machine has the following guards: + +- **Sol Payment**: This guard ensures the minting wallet has to pay a configured amount of SOL to a configured destination wallet. +- **Start Date**: This guard ensures minting can only start after the configured time. +- **Mint Limit**: This guard ensures each wallet cannot mint more than a configured amount. +- **Bot Tax**: This guard is a bit special. It doesn’t guard against anything but it changes the behaviour of a failed mint to prevent bots from minting Candy Machines. When this guard is activated, if any other activated guard fails to validate the mint, it will charge a small configured amount of SOL to the wallet that tried to mint. + +What we end up with is a bot-protected Candy Machine that charges SOL, launches at a specific time and only allows a limited amount of mints per wallet. Here’s a concrete example. + +{% diagram %} +{% node %} +{% node #candy-machine label="Core Candy Machine" theme="blue" /%} +{% node label="Settings" /%} +{% node #items label="Items" /%} +{% node #guards %} +Guards: + +- Sol Payment (0.1 SOL) +- Start Date (Jan 6th) +- Mint Limit (1) +- Bot Tax (0.01 SOL) + +{% /node %} +{% /node %} + +{% node parent="candy-machine" x="250" %} +{% node #mints label="Assets" theme="pink" /%} +{% node #mint-1 label="#1: Wallet A (1 SOL) on Jan 5th" theme="pink" /%} +{% node #mint-2 label="#2: Wallet B (3 SOL) on Jan 6th" theme="pink" /%} +{% node #mint-3 label="#3: Wallet B (2 SOL) on Jan 6th" theme="pink" /%} +{% node #mint-4 label="#4: Wallet C (0.5 SOL) on Jan 6th" theme="pink" /%} +{% /node %} +{% node #fail-1 parent="mints" x="250" theme="red" %} +Too early {% .text-xs %} \ +Bot tax charged +{% /node %} +{% node #nft-2 parent="fail-1" y="50" label="Asset" theme="blue" /%} +{% node #fail-3 parent="nft-2" y="50" theme="red" %} +Minted 1 already {% .text-xs %} \ +Bot tax charged +{% /node %} +{% node #fail-4 parent="fail-3" y="50" theme="red" %} +Not enough SOL {% .text-xs %} \ +Bot tax charged +{% /node %} + +{% edge from="candy-machine" to="mint-1" /%} +{% edge from="candy-machine" to="mint-2" /%} +{% edge from="candy-machine" to="mint-3" /%} +{% edge from="candy-machine" to="mint-4" /%} +{% edge from="mint-1" to="fail-1" path="bezier" /%} +{% edge from="mint-2" to="nft-2" path="bezier" /%} +{% edge from="mint-3" to="fail-3" path="bezier" /%} +{% edge from="mint-4" to="fail-4" path="bezier" /%} +{% /diagram %} + +As you can see, with more than 23 default guards and the ability to create custom guards, it enables creators to cherry-pick the features that matters to them and compose their perfect Candy Machine. This is such a powerful feature that we’ve dedicated many pages to it. The best place to start to know more about guards is the [Candy Guards](/core-candy-machine/guards) page. +Documents the latest changes. \ No newline at end of file diff --git a/src/pages/core-candy-machine/index.md b/src/pages/core-candy-machine/index.md index 942cb706..55cb68e0 100644 --- a/src/pages/core-candy-machine/index.md +++ b/src/pages/core-candy-machine/index.md @@ -4,22 +4,25 @@ metaTitle: Overview | Core Candy Machine description: Provides a high-level overview of Core Candy Machines. --- -The Metaplex Protocol **Candy Machine** is the leading minting and distribution program for fair NFT collection launches on Solana. With the introduction of the `Metaplex Core Protocol` simplifying the NFT process on Solana it was only fitting for a Core edition of the Candy Machine to come to the masses. Much like its name suggests, you can think of a Candy Machine as a temporary structure which is first loaded by creators and then unloaded by buyers. It allows creators to bring their digital assets onchain in a secure and customizable way. {% .lead %} +The leading minting and distribution program for fair NFT launches on Solana. -The name refers to the vending machines that dispense candy for coins via a mechanical crank. In this case the candy are NFTs and the payment is SOL or a SPL token. +Metaplex Candy Machine is a tool that allows creators to sell or distribute large-scale NFT collections by simplifying complex processes and adding customizable rules such as time gates, supply limits, and anti-bot protections to ensure fair access for every buyer. {% .lead %} + + +As the name suggests, its mechanism works like a `candy machine`: creators load it with `candies` (NFTs), and buyers obtain them, without possibility of choosing, by paying SOL or SPL tokens. + +**Note**: This is the [Metaplex Core](/core) version of Candy Machine, if you want to mint Metaplex Token Metadata NFTs [please refer to Candy Machine V3 instead](https://developers.metaplex.com/candy-machine/) {% quick-links %} -{% quick-link title="Getting Started" icon="InboxArrowDown" href="/core-candy-machine/getting-started" description="Find the language or library of your choice and get started with Candy Machines." /%} +{% quick-link title="Getting Started" icon="InboxArrowDown" href="/core-candy-machine/getting-started" description="Choose your preferred language or library and start building with Candy Machine." /%} -{% quick-link title="API reference" icon="JavaScript" href="https://mpl-core-candy-machine.typedoc.metaplex.com/" target="_blank" description="Check out the Javascript API docs." /%} +{% quick-link title="Guides" icon="InboxArrowDown" href="/core-candy-machine/guides" description="Explore ready-to-use examples for implementing Candy Machine." /%} +{% quick-link title="API Reference" icon="JavaScript" href="https://mpl-core-candy-machine.typedoc.metaplex.com/" target="_blank" description="Browse the JavaScript API documentation." /%} -{% quick-link title="API reference" icon="Rust" href="https://docs.rs/mpl-core-candy-machine-core/" target="_blank" description="Check out the Rust API docs." /%} -{% /quick-links %} +{% quick-link title="API Reference" icon="Rust" href="https://docs.rs/mpl-core-candy-machine-core/" target="_blank" description="Browse the Rust API documentation." /%} -{% callout %} -This documentation refers to the latest iteration of Candy Machine known as Core Candy Machine. It allows minting [Core](/core) Assets. If you want to mint Metaplex Token Metadata NFTs [please refer to Candy Machine V3 instead](https://developers.metaplex.com/candy-machine/). -{% /callout %} +{% /quick-links %} diff --git a/src/pages/core-candy-machine/overview.md b/src/pages/core-candy-machine/overview.md deleted file mode 100644 index 0381a186..00000000 --- a/src/pages/core-candy-machine/overview.md +++ /dev/null @@ -1,210 +0,0 @@ ---- -title: Program Overview -metaTitle: Program Overview | Core Candy Machine -description: An overview of the Core Candy Machine program and its feature sets to help you create a minting experience. ---- - -## Introduction - -By September 2022, 78% of all NFTs in Solana were minted through Metaplex’s Candy Machine. This includes most of the well known NFT projects in the Solana ecosystem. Come 2024 Metaplex introduced the `Core` protocol which redefines NFTs on Solana and with it a new Candy Machine to accommodate the same minting mechanics users loved for the `Core` standard. - -Here are some of the features it offers. - -- Accept payments in SOL, NFTs or any Solana token. -- Restrict your launch via start/end dates, mint limits, third party signers, etc. -- Protect your launch against bots via configurable bot taxes and gatekeepers like Captchas. -- Restrict minting to specific Asset/NFT/Token holders or to a curated list of wallets. -- Create multiple minting groups with different sets of rules. -- Reveal your Assets after the launch whilst allowing your users to verify that information. -- And so much more! - -Interested? Let’s give you a little tour of how `Core Candy Machines` work! - -## The Lifecycle of a Core Candy Machine - -The very first step is for the creator to create a new Core Candy Machine and configure it however they want. - -{% diagram %} -{% node #action label="1. Create & Configure" theme="pink" /%} -{% node parent="action" x="250" %} -{% node #candy-machine label="Core Candy Machine" theme="blue" /%} -{% node label="Settings" /%} -{% /node %} -{% edge from="action" to="candy-machine" path="straight" /%} -{% /diagram %} - -The created Core Candy Machine keeps track its own settings which helps us understand how all of its NFTs should be created. For instance, there is a `collection` parameter which will be assigned to all Assets created from this Core Candy Machine. We will see how to create and configure Core Candy Machines in more details in the **Features** section of the menu. - -However, we still don’t know which Assets should be minted from that Core Candy Machine. In other words, the Core Candy Machine is not currently loaded. Our next step, is to insert items. - -{% diagram %} -{% node #action-1 label="1. Create & Configure" theme="pink" /%} -{% node #action-2 label="2. Insert Items" parent="action-1" y="50" theme="pink" /%} -{% node parent="action-1" x="250" %} -{% node #candy-machine label="Core Candy Machine" theme="blue" /%} -{% node label="Settings" /%} -{% node #item-1 label="Item 1" /%} -{% node #item-2 label="Item 2" /%} -{% node #item-3 label="Item 3" /%} -{% node #item-rest label="..." /%} -{% /node %} -{% edge from="action-1" to="candy-machine" path="straight" /%} -{% edge from="action-2" to="item-1" /%} -{% edge from="action-2" to="item-2" /%} -{% edge from="action-2" to="item-3" /%} -{% edge from="action-2" to="item-rest" /%} -{% /diagram %} - -Each item is composed of two parameters: - -- A `name`: The name of the Asset. -- A `uri`: The URI pointing to the [JSON metadata](https://developers.metaplex.com/token-metadata/token-standard#the-non-fungible-standard) of the Asset. This implies that the JSON metadata has already been uploaded via either an onchain (e.g. Arweave, IPFS) or off-chain (e.g. AWS, your own server) storage provider. The tools that you can use to create the Candy Machine, like Sugar or the JS SDK offer helpers to do so. - -All other parameters are shared between Assets and are therefore kept in the settings of the Candy Machine directly to avoid repetition. See [Inserting Items](/core-candy-machine/insert-items) for more details. - -Notice how, at this point, no real Assets have been created yet. We are simply loading the Candy Machine with all the data it needs to **create Assets on-demand**, at mint time. Which brings us to the next step. - -{% diagram %} -{% node #action-1 label="1. Create & Configure" theme="pink" /%} -{% node #action-2 label="2. Insert Items" parent="action-1" y="50" theme="pink" /%} - -{% node parent="action-1" x="250" %} -{% node #candy-machine label="Candy Machine" theme="blue" /%} -{% node label="Settings" /%} -{% node #item-1 label="Item 1" /%} -{% node #item-2 label="Item 2" /%} -{% node #item-3 label="Item 3" /%} -{% node #item-rest label="..." /%} -{% /node %} - -{% node parent="candy-machine" x="180" y="20" %} -{% node #mint label="3. Mint" theme="pink" /%} -{% node #mint-1 label="Mint #1" theme="pink" /%} -{% node #mint-2 label="Mint #2" theme="pink" /%} -{% node #mint-3 label="Mint #3" theme="pink" /%} -{% /node %} - -{% node #nft-1 parent="mint" x="120" label="Asset" theme="blue" /%} -{% node #nft-2 parent="nft-1" y="50" label="Asset" theme="blue" /%} -{% node #nft-3 parent="nft-2" y="50" label="Asset" theme="blue" /%} - -{% edge from="action-1" to="candy-machine" path="straight" /%} -{% edge from="action-2" to="item-1" /%} -{% edge from="action-2" to="item-2" /%} -{% edge from="action-2" to="item-3" /%} -{% edge from="action-2" to="item-rest" /%} -{% edge from="item-1" to="mint-1" /%} -{% edge from="item-2" to="mint-2" /%} -{% edge from="item-3" to="mint-3" /%} -{% edge from="mint-1" to="nft-1" path="bezier" /%} -{% edge from="mint-2" to="nft-2" path="bezier" /%} -{% edge from="mint-3" to="nft-3" path="bezier" /%} -{% /diagram %} - -Once the Candy Machine is loaded and all pre-configured conditions are met, users can start minting Assets from it. It’s only at this point that an Asset is created on the Solana blockchain. Note that, before minting, some users may need to perform additional verification steps — such as doing a Captcha or sending a Merkle Proof. See [Minting](/core-candy-machine/mint) for more details. - -Once all Assets have been minted from a Candy Machine, it has served its purpose and can safely be deleted to free some storage space on the blockchain and claim some rent back. See [Withdrawing a Candy Machine](/core-candy-machine/withdrawing-a-candy-machine) for more details. - -{% diagram %} -{% node #action-1 label="4. Delete" theme="pink" /%} -{% node parent="action-1" x="150" %} -{% node #candy-machine label="Candy Machine" theme="blue" /%} -{% node label="Settings" /%} -{% node #item-1 label="Item 1" /%} -{% node #item-2 label="Item 2" /%} -{% node #item-3 label="Item 3" /%} -{% node #item-rest label="..." /%} -{% /node %} -{% node #nft-1 parent="candy-machine" x="200" label="Asset" theme="blue" /%} -{% node #nft-2 parent="nft-1" y="50" label="Asset" theme="blue" /%} -{% node #nft-3 parent="nft-2" y="50" label="Asset" theme="blue" /%} -{% edge from="action-1" to="candy-machine" path="straight" /%} -{% /diagram %} - -## Core Candy Machine Account Structure - -Explain what data is stored and what role that data has for the user. - -{% totem %} -{% totem-accordion title="On Chain Core Candy Machine Data Structure" %} - -The onchain account structure of an MPL Core Asset. [Link](https://github.com/metaplex-foundation/mpl-core/blob/ce5d16f2de3c0038caae81a8c6496420b1a0462a/programs/mpl-core/src/state/asset.rs#L19) - -| Name | Type | Size | Description | | -| -------------- | ------- | ---- | -------------------------------------------------------- | --- | -| version | u8 | 1 | version of the Candy Machine | | -| features | [u8; 6] | 6 | What feature flags are enabled for the Candy Machine | | -| authority | Pubkey | 32 | The Authority of the Candy Machine | | -| mint_authority | Pubkey | 32 | The Mint Authority of the Candy Machine | | -| collection | Pubkey | 32 | The collection address assigned to the Candy Machine | | -| items_redeemed | u64 | | How many items have been redeemed from the Candy Machine | | - -{% /totem-accordion %} -{% /totem %} - -## Candy Guards - -Now that we understand how Core Candy Machines work, let’s dig into the various ways creators can protect and customize the mint process of their Core Candy Machine. - -Creators can use what we call “**Guards**” to add various features to their Core Candy Machine. The Metaplex Core Candy Machine ships with an additional Solana Program called **Candy Guard** that ships with [**a total of 23 default guards**](/core-candy-machine/guards). By using an additional program, it allows advanced developers to fork the default Candy Guard program to create their own custom guards whilst still being able to rely on the main Candy Machine program. - -Each guard can be enabled and configured at will so creators can pick and choose the features they need. Disabling all guards would be equivalent to allowing anyone to mint our NFTs for free at any time, which is likely not what we want. So let’s have a look at a few guards to create a more realistic example. - -Say a Core Candy Machine has the following guards: - -- **Sol Payment**: This guard ensures the minting wallet has to pay a configured amount of SOL to a configured destination wallet. -- **Start Date**: This guard ensures minting can only start after the configured time. -- **Mint Limit**: This guard ensures each wallet cannot mint more than a configured amount. -- **Bot Tax**: This guard is a bit special. It doesn’t guard against anything but it changes the behaviour of a failed mint to prevent bots from minting Candy Machines. When this guard is activated, if any other activated guard fails to validate the mint, it will charge a small configured amount of SOL to the wallet that tried to mint. - -What we end up with is a bot-protected Candy Machine that charges SOL, launches at a specific time and only allows a limited amount of mints per wallet. Here’s a concrete example. - -{% diagram %} -{% node %} -{% node #candy-machine label="Core Candy Machine" theme="blue" /%} -{% node label="Settings" /%} -{% node #items label="Items" /%} -{% node #guards %} -Guards: - -- Sol Payment (0.1 SOL) -- Start Date (Jan 6th) -- Mint Limit (1) -- Bot Tax (0.01 SOL) - -{% /node %} -{% /node %} - -{% node parent="candy-machine" x="250" %} -{% node #mints label="Assets" theme="pink" /%} -{% node #mint-1 label="#1: Wallet A (1 SOL) on Jan 5th" theme="pink" /%} -{% node #mint-2 label="#2: Wallet B (3 SOL) on Jan 6th" theme="pink" /%} -{% node #mint-3 label="#3: Wallet B (2 SOL) on Jan 6th" theme="pink" /%} -{% node #mint-4 label="#4: Wallet C (0.5 SOL) on Jan 6th" theme="pink" /%} -{% /node %} -{% node #fail-1 parent="mints" x="250" theme="red" %} -Too early {% .text-xs %} \ -Bot tax charged -{% /node %} -{% node #nft-2 parent="fail-1" y="50" label="Asset" theme="blue" /%} -{% node #fail-3 parent="nft-2" y="50" theme="red" %} -Minted 1 already {% .text-xs %} \ -Bot tax charged -{% /node %} -{% node #fail-4 parent="fail-3" y="50" theme="red" %} -Not enough SOL {% .text-xs %} \ -Bot tax charged -{% /node %} - -{% edge from="candy-machine" to="mint-1" /%} -{% edge from="candy-machine" to="mint-2" /%} -{% edge from="candy-machine" to="mint-3" /%} -{% edge from="candy-machine" to="mint-4" /%} -{% edge from="mint-1" to="fail-1" path="bezier" /%} -{% edge from="mint-2" to="nft-2" path="bezier" /%} -{% edge from="mint-3" to="fail-3" path="bezier" /%} -{% edge from="mint-4" to="fail-4" path="bezier" /%} -{% /diagram %} - -As you can see, with more than 23 default guards and the ability to create custom guards, it enables creators to cherry-pick the features that matters to them and compose their perfect Candy Machine. This is such a powerful feature that we’ve dedicated many pages to it. The best place to start to know more about guards is the [Candy Guards](/core-candy-machine/guards) page. -Documents the latest changes. From 69aba42c39fbbc344ee50080e7c23cda4738e23c Mon Sep 17 00:00:00 2001 From: L0STE <125566964+L0STE@users.noreply.github.com> Date: Fri, 13 Dec 2024 18:00:48 +0100 Subject: [PATCH 2/6] updating core candy machine done --- src/pages/core-candy-machine/create.md | 397 +++++------------- .../getting-started/index.md | 50 ++- src/pages/core-candy-machine/update.md | 182 ++++---- 3 files changed, 223 insertions(+), 406 deletions(-) diff --git a/src/pages/core-candy-machine/create.md b/src/pages/core-candy-machine/create.md index 947678f9..814d81cc 100644 --- a/src/pages/core-candy-machine/create.md +++ b/src/pages/core-candy-machine/create.md @@ -1,18 +1,40 @@ --- title: Creating a Core Candy Machine metaTitle: Creating a Core Candy Machine | Core Candy Machine -description: Learn how to create your Core Candy Machine and it's various settings in both Javascript and Rust. +description: Learn how to create a Core Candy Machine and it's various settings in both Javascript and Rust. --- -## Prerequisites +**Note**: Before creating the Candy Machine, ensure that all assets intended for loading are fully prepared and uploaded to a decentralized storage solution. If you're unsure how to proceed, follow to this guide: [Preparing the Candy Machine Assets](/core-candy-machine/guides/preparing-assets) -- [Prepared Assets](/core-candy-machine/preparing-assets) -- [Create Core Collection](/core/collections#creating-a-collection) - -If you wish to create your Core Candy Machine Assets into a collection (new or existing) you will need to supply the Core Collection upon creation of the Core Candy Machine. +Additionally, you'll need a Core Collection (new or existing) where all the assets created by the Candy Machine will be included. If you're unfamiliar with creating a Core Collection, follow this guide: [Create a Core Collection](/core/guides/javascript/how-to-create-a-core-collection-with-javascript) ## Creating a Candy Machine +All arguments passed in the `create` function define the behavior, ownership, and configuration of the Candy Machine. + +Below is a detailed breakdown of each argument, including required and optional parameters: + +| Name | Type | Description | +|------------------------------|-------------------------------|--------------------------------------------------------------------------------------------------| +| `candyMachine` | `signer` | A newly generated keypair/signer used to create the Core Candy Machine. | +| `authorityPda` (optional) | `publicKey` | PDA used to verify minted assets to the collection. Auto-calculated if left undefined. | +| `authority` (optional) | `publicKey` | The wallet/public key that will be the authority over the Core Candy Machine. | +| `payer` (optional) | `signer` | Wallet that pays for the transaction and rent costs. Defaults to the signer. | +| `collection` | `publicKey` | The collection into which the Core Candy Machine will create assets. | +| `collectionUpdateAuthority` | `signer` | Signer required to approve a delegate verifying created assets in the collection. | +| `itemsAvailable` | `number` | Number of items being loaded into the Core Candy Machine. | +| `isMutable` | `boolean` | Boolean indicating whether the assets are mutable upon creation. | +| `configLineSettings`(optional)| [Link](#with-config-line-settings) | Configuration settings for asset lines. | +| `hiddenSettings` (optional) | [Link](#with-hidden-settings) | Optional settings for hiding asset information. | +| `guards` (optional) | [Link](#with-guards) | Optional settings for adding [Candy Guards](#candy-guards). | + +When creating a Candy Machine, there are different configurations that can modify its behavior. The most important ones include: +- [ConfigLineSettings](#with-config-line-settings): Reduces the space required for the Candy Machine by not storing identical name and URI prefixes linked to all the assets. +- [HiddenSettings](#with-hidden-settings): Allows minting the same asset to all purchasers while storing a hash of data that validates each updated/revealed NFT correctly. +- [Guards](#with-guards): Adds specific Candy Guards to the Candy Machine. + +If no additional behavior or configuration is required, the code to create a Candy Machine will look like this: + {% dialect-switcher title="Create a Core Candy Machine" %} {% dialect title="JavaScript" id="js" %} @@ -37,239 +59,25 @@ await createIx.sendAndConfirm(umi) {% /dialect %} {% /dialect-switcher %} -### Args - -Available arguments that can be passed into the createCandyMachine function. - -A newly generated keypair/signer that is used to create the Core Candy Machine. - -{% dialect-switcher title="Create CandyMachine Args" %} -{% dialect title="JavaScript" id="js" %} - -| name | type | -| ------------------------- | ----------------------------- | -| candyMachine | signer | -| authorityPda (optional) | publicKey | -| authority (optional) | publicKey | -| payer (optional) | signer | -| collection | publicKey | -| collectionUpdateAuthority | signer | -| itemsAvailable | number | -| isMutable | boolean | -| configLineSettings | [link](#config-line-settings) | -| hiddenSettings | [link](#hidden-settings) | - -{% /dialect %} -{% dialect title="Rust" id="rust" %} - -| name | type | -| ------------------------- | ----------------------------- | -| candyMachine | signer | -| authorityPda (optional) | pubkey | -| authority (optional) | pubkey | -| payer (optional) | signer | -| collection | pubkey | -| collectionUpdateAuthority | signer | -| itemsAvailable | number | -| isMutable | boolean | -| configLineSettings | [link](#config-line-settings) | -| hiddenSettings | [link](#hidden-settings) | - -{% /dialect %} -{% /dialect-switcher %} - -### authorityPda (optional) - -{% dialect-switcher title="Authority" %} -{% dialect title="JavaScript" id="js" %} - -```ts -authorityPda: string -``` - -{% /dialect %} -{% /dialect-switcher %} - -The authorityPda field is the PDA used to verify minted Assets to the collection. This is optional an is calculated automatically based on default seeds if left. - -### authority (optional) - -{% dialect-switcher title="authority" %} -{% dialect title="JavaScript" id="js" %} - -```ts -authority: string -``` - -{% /dialect %} -{% /dialect-switcher %} - -### payer (optional) - -The wallet that pays for the transaction and rent costs. Defaults to signer. - -{% dialect-switcher title="authority" %} -{% dialect title="JavaScript" id="js" %} - -```ts -payer: publicKey -``` - -{% /dialect %} -{% /dialect-switcher %} - -The authority field is the wallet/publicKey that will be the authority over the Core Candy Machine. +### with Config Line Settings -### Collection +Config Line Settings is an optional feature that helps reduce the Core Candy Machine's rent cost by minimizing stored asset data. -The collection the Core Candy Machine will create Assets into. +This is done by storing common prefix for Assets and URI once, and allowing then the Core Candy Machine to append unique indexes automatically. -{% dialect-switcher title="authority" %} -{% dialect title="JavaScript" id="js" %} +For example if your assets are named `Example Asset #1` through `Example Asset #1000`, storing the prefix Example Asset # once and appending numbers from 1 to 1000 saves storing the same prefix 1000 times, reducing storage by 15,000 bytes. -```ts -collection: publicKey -``` - -{% /dialect %} -{% /dialect-switcher %} +The same approach applies to the URI prefix, further lowering rent costs. -### Collection Update Authority +To use it, we'll need to create a specific struct. Below is a detailed breakdown of each argument present in the `ConfigLineSettings` Struct: -Update authority of the collection. This needs to be a signer so the Candy Machine can approve a delegate to verify created Assets to the Collection. - -{% dialect-switcher title="authority" %} -{% dialect title="JavaScript" id="js" %} - -```ts -collectionUpdateAuthority: signer -``` - -{% /dialect %} -{% /dialect-switcher %} - - - -### itemsAvailable - -The number of items being loaded into the Core Candy Machine. - -{% dialect-switcher title="itemsAvailable" %} -{% dialect title="JavaScript" id="js" %} - -```ts -itemsAvailable: number -``` - -{% /dialect %} -{% /dialect-switcher %} - -### Is Mutable - -A boolean that marks an Asset as mutable or immutable upon creation. - -{% dialect-switcher title="isMutable" %} -{% dialect title="JavaScript" id="js" %} - -```ts -isMutable: boolean -``` - -{% /dialect %} -{% /dialect-switcher %} - -### Config Line Settings - -Config Line Settings is an optional field that allows advanced options of adding your Asset data to the Core Candy Machine making the Core Candy Machine's rent cost significantly cheaper. - -By storing the Assets name and URI prefix into the Core Candy Machine the data required to be stored is significantly reduced as you will not be storing the same name and URI for every single Asset. - -For example if all your Assets had the same naming structure of `Example Asset #1` through to `Example Asset #1000` this would normally require you to store the string `Example Asset #` 1000 times, taking up 15,000 bytes. - -By storing the prefix of the name in the the Core Candy Machine and letting the Core Candy Machine append the index number created to the string you save these 15,000 bytes in rent cost. - -This also applies to the URI prefix. - -{% dialect-switcher title="ConfigLineSettings Object" %} -{% dialect title="JavaScript" id="js" %} - -```ts -ConfigLineSettings = { - prefixName: string; - nameLength: number; - prefixUri: string; - uriLength: number; - isSequential: boolean; -} -``` - -{% /dialect %} -{% /dialect-switcher %} - -#### prefixName - -This stores the name prefix of the nfts and appends the minted index to the end of the name upon mint. - -If your Asset's have a naming structure of `Example Asset #1` then your prefix would be `Example Asset #`. Upon mint the Core Candy Machine will attach the index to the end of the string. - -#### nameLength - -The maximum length for the name of each inserted item excluding the name prefix - -For Example given... -- a candy machine containing `1000` items. -- The name of each item is `Example Asset #X` where X is the item’s index starting from 1. - -... would result in 19 characters that would need to be stored. 15 characters for “My NFT Project #” and 4 characters for the highest number which is “1000”. When using the `prefixName` the `nameLength` instead can be reduced to 4. - -#### prefixUri - -The base URI of your metadata excluding the variable identification id. - -If your Asset's will have a metadata URI of `https://example.com/metadata/0.json` then your base metadata URI will be `https://example.com/metadata/`. - -#### uriLength - -The maximum lengths of your URIs excluding the `prefixUri`. - -For Example given... -- a base URI ` https://arweave.net/` with 20 characters. -- and a unique unifier with a maximum length of 43 characters - -... without prefix would result in 63 required characters to store. When using the `prefixUri` the `uriLength` can be reduced by 20 characters for `https://arweave.net/` to the 43 characters for the unique identifier. - -#### isSequential - -Indicates whether to use a sequential index generator or not. If false the Candy Machine will mint randomly. - -#### configLineSettings +| Field | Type | Description | +|------------------|------------|----------------------------------------------------------------------------------------------| +| `prefixName` | `string` | Stores the name prefix of the NFTs. The minted index is appended to create unique names. | +| `nameLength` | `number` | Maximum length of the NFT name excluding the prefix. | +| `prefixUri` | `string` | Base URI of the metadata, excluding the unique identifier. | +| `uriLength` | `number` | Maximum length of the URI excluding the base `prefixUri`. | +| `isSequential` | `boolean` | Indicates whether to use sequential or random minting. | Here is an example of creating a Core Candy Machine with `configLineSettings` applied: @@ -284,10 +92,7 @@ const candyMachine = generateSigner(umi) const coreCollection = publicKey('11111111111111111111111111111111') const createIx = await create(umi, { - candyMachine, - collection: coreCollection, - collectionUpdateAuthority: umi.identity, - itemsAvailable: 5000, + // ... configLineSettings: some({ prefixName: 'Example Asset #', nameLength: 15, @@ -303,43 +108,15 @@ await createIx.sendAndConfirm(umi) {% /dialect %} {% /dialect-switcher %} -### Hidden Settings - -Hidden settings allows the Core Candy Machine to mint exactly the same Asset to all purchasers. The design principle behind this is to allow the popular 'reveal' mechanic to take to take place at a later date. It also allows printing Core Editions when combined with the Edition Guard. - -{% dialect-switcher title="Hidden Settings" %} -{% dialect title="JavaScript" id="js" %} - -```ts -hiddenSettings = { - name: string, - uri: string, - hash: Uint8Array, -} -``` - -{% /dialect %} -{% /dialect-switcher %} - -#### name +### with Hidden Settings -The name that appears on all Assets minted with hidden settings enabled. Note that, just like for the prefixes of the Config Line Settings, special variables can be used for the Name and URI of the Hidden Settings. As a reminder, these variables are: +Hidden Settings is an optional feature that mints the same asset to all buyers, allowing creators to `reveal` the actual assets at a later time. -- `$ID$`: This will be replaced by the index of the minted Asset starting at 0. -- `$ID+1$`: This will be replaced by the index of the minted Asset starting at 1. +**Note**: This feature also supports printing Core Editions when used with the Edition Guard. -You should use this to be able to match the Assets that you want to your revealed data. +To ensure the revealed NFT data hasn’t been manipulated (such as moving rare assets to specific holders), creators must submit and save a hash that links each asset's URI with its corresponding number during the creation of the Candy Machine. -#### uri - -The uri that appears on all Assets minted with hidden settings enabled. - -#### hash - -The purpose behind the hash is to store a cryptographic hash/checksum of a piece of data that validates that each updated/revealed nft is the correct one matched to the index minted from the Candy Machine. This allows users to check the validation and if you have altered the data shared and in fact that `Hidden NFT #39` is also `Revealed NFT #39` and that the original data hasn't been tampered with to move rares around to specific people/holders. - -{% dialect-switcher title="Hashing Reveal Data" %} -{% dialect title="JavaScript" id="js" %} +This can be done with the following code: ```ts import crypto from 'crypto' @@ -356,12 +133,17 @@ const hash = crypto.createHash('sha256').update(string).digest() console.log(hash) ``` -{% /dialect %} -{% /dialect-switcher %} +To use it, we'll need to create a specific struct. Below is a detailed breakdown of each argument present in the `HiddenSettings` Struct: + +| Field | Type | Description | +|-------------|---------------|-------------------------------------------------------------------------------------------------| +| `name` | `string` | The name applied to all minted assets. Supports special variables like `$ID$` and `$ID+1$`. | +| `uri` | `string` | The URI applied to all minted assets. | +| `hash` | `Uint8Array` | Cryptographic hash used to verify that the revealed NFTs match the originally minted data. | -#### Example Core Candy Machine with Hidden Settings +Here is an example of creating a Core Candy Machine with `hiddenSettings` applied: -{% dialect-switcher title="Create a Candy Machine With Hidden Settings" %} +{% dialect-switcher title="Create a Core Candy Machine with hiddenSettings" %} {% dialect title="JavaScript" id="js" %} ```ts @@ -380,11 +162,7 @@ const string = JSON.stringify(revealData) const hash = crypto.createHash('sha256').update(string).digest() const createIx = await create(umi, { - candyMachine, - collectionMint: collectionMint.publicKey, - collectionUpdateAuthority, - sellerFeeBasisPoints: percentAmount(10), - itemsAvailable: 5000, + // ... hiddenSettings: { name: "Hidden Asset", uri: "https://example.com/hidden-asset.json", @@ -398,19 +176,64 @@ await createIx.sendAndConfirm(umi) {% /dialect %} {% /dialect-switcher %} -## Creating a Core Candy Machine with guards +### with Guards -To create a `Core Candy Machine` with `Guards` you can supply the `guards:` field during creation and supply the default guards you with to apply to the Candy Machine.s +Candy Guards is an optional feature that adds extra functionalities to a Core Candy Machine. -So far, the Core Candy Machine we created did not have any guards enabled. Now that we know all the guards available to us, let’s see how we can set up new Candy Machines with some guards enabled. +To enable guards, pass the `some()` attribute along with the required data for each specific guard. Any guard set to `none()` or not provided will be disabled by default. -The concrete implementation will depend on which SDK you are using (see below) but the main idea is that you enable guards by providing their required settings. Any guard that has not been set up will be disabled. +If you want to learn more about what Candy Guards are available, refer to this: [Candy Guards Overview]() + +Here's a list of all the Candy Guards available and the individual attributes: + +{% totem %} + +{% totem-accordion title="Candy Guards Attributes" %} + +| Guard Name | Arguments | +|----------------------------|--------------------------------------------------------------------------| +| **addressGate** | { `address`: PublicKey } | +| **allocation** | { `id`: number, `limit`: number } | +| **allowList** | { `merkleRoot`: Uint8Array } | +| **assetBurn** | { `requiredCollection`: PublicKey } | +| **assetBurnMulti** | { `num`: number, `requiredCollection`: PublicKey } | +| **assetGate** | { `requiredCollection`: PublicKey } | +| **assetMintLimit** | { `id`: number, `limit`: number, `requiredCollection`: PublicKey } | +| **assetPayment** | { `destination`: PublicKey, `requiredCollection`: PublicKey } | +| **assetPaymentMulti** | { `destination`: PublicKey, `num`: number, `requiredCollection`: PublicKey } | +| **botTax** | { `lamports`: SolAmount, `lastInstruction`: boolean } | +| **edition** | { `editionStartOffset`: number } | +| **endDate** | { `date`: DateTimeInput } | +| **freezeSolPayment** | { `destination`: PublicKey, `lamports`: SolAmount } | +| **freezeTokenPayment** | { `amount`: number | bigint, `mint`: PublicKey, `destination`: PublicKey } | +| **gatekeeper** | { `expireOnUse`: boolean, `gatekeeperNetwork`: PublicKey } | +| **mintLimit** | { `id`: number, `limit`: number } | +| **nftBurn** | { `requiredCollection`: PublicKey } | +| **nftGate** | { `requiredCollection`: PublicKey } | +| **nftMintLimit** | { `id`: number, `limit`: number, `requiredCollection`: PublicKey } | +| **nftPayment** | { `destination`: PublicKey, `requiredCollection`: PublicKey } | +| **programGate** | { `additional`: PublicKey[] } | +| **redeemedAmount** | { `maximum`: number | bigint } | +| **solFixedFee** | { `destination`: PublicKey, `lamports`: SolAmount } | +| **solPayment** | { `lamports`: SolAmount, `destination`: PublicKey } | +| **startDate** | { `date`: DateTimeInput } | +| **thirdPartySigner** | { `signerKey`: PublicKey } | +| **token2022Payment** | { `amount`: number | bigint, `destinationAta`: PublicKey, `mint`: PublicKey } | +| **tokenBurn** | { `amount`: number | bigint, `mint`: PublicKey } | +| **tokenGate** | { `amount`: number | bigint, `mint`: PublicKey } | +| **tokenPayment** | { `amount`: number | bigint, `destinationAta`: PublicKey, `mint`: PublicKey } | +| **vanityMint** | { `regex`: string } | + + +{% /totem-accordion %} + +{% /totem %} + +Here is an example of creating a Core Candy Machine with `guards` applied: {% dialect-switcher title="Create a Core Candy Machine with guards" %} {% dialect title="JavaScript" id="js" %} - - ```ts import { some, sol, dateTime } from '@metaplex-foundation/umi' @@ -420,14 +243,12 @@ const createIx = await create(umi, { botTax: some({ lamports: sol(0.01), lastInstruction: true }), solPayment: some({ lamports: sol(1.5), destination: treasury }), startDate: some({ date: dateTime('2023-04-04T16:00:00Z') }), - // All other guards are disabled... + // ... }, }) await createIx.sendAndConfirm(umi) ``` -API References: [create](https://mpl-core-candy-machine.typedoc.metaplex.com/functions/create.html), [DefaultGuardSetArgs](https://mpl-core-candy-machine.typedoc.metaplex.com/types/DefaultGuardSetArgs.html) - {% /dialect %} {% /dialect-switcher %} diff --git a/src/pages/core-candy-machine/getting-started/index.md b/src/pages/core-candy-machine/getting-started/index.md index 123fcc8a..6db33bd4 100644 --- a/src/pages/core-candy-machine/getting-started/index.md +++ b/src/pages/core-candy-machine/getting-started/index.md @@ -67,7 +67,7 @@ Start by creating a new Core Candy Machine and configuring it with custom settin **Note**: Candy Guards are modular code that adds custom behavior to the Candy Machine. -Learn more about [How to create a Candy Machine]() +To learn more about how to create a Candy Machine, follow this link: [Create a Candy Machine]() ### Load Items @@ -79,40 +79,53 @@ Each item to load includes: **Note**: If you're not familiar with how to upload metadata, you can follow [this paragraph](/core/guides/javascript/how-to-create-a-core-nft-asset-with-javascript#creating-the-metadata-for-the-asset) or use Sugar! -Learn more about [How to load a Candy Machine]() +To learn more about how to load a Candy Machine, follow this link: [Load a Candy Machine]() ### Mint Asset Once all items are loaded into the Candy Machine and pre-configured conditions are met, users can begin minting assets. -**Note**: To let the user easily access a way to mint from the candy machine, we've created this guide: [Create a Website for minting Assets from your Core Candy Machine](/guides/create-a-core-candy-machine-ui) +**Note**: To let the user easily access a way to mint from the candy machine, we've created this guide: [Create a Website for minting Assets from your Core Candy Machine](/core-candy-machine/guides/create-a-core-candy-machine-ui) -Learn more about [How to Mint from a Candy Machine]() + +To learn more about how to Mint from a Candy Machine, follow this link: [Mint from a Candy Machine]() ### Delete and Withdraw After the Candy Machine has fulfilled its purpose, it can be safely deleted to reclaim the rent paid for storing its data on-chain. -Learn more about [How to Delete a Candy Machine]() - -----todo +To learn more about how to delete a Candy Machine, follow this link: [Delete a Candy Machine]() ## Candy Guards -Now that we understand how Core Candy Machines work, let’s dig into the various ways creators can protect and customize the mint process of their Core Candy Machine. +Creators can use `Candy Guards` to secure and customize the minting process of their Core Candy Machine by leveraging an additional program with 23 built-in guards! + +For a list of all the available guards and how to use them, follow this link: [Candy Guard Overview]() + +**Note**: Metaplex Candy Machine is designed to be a large-scale NFT collections distributor and doesn't natively support setting a price for the NFTs. To add pricing, configure the Sol Payment or SPL token payment guard! + +### Custom Guards + +Additionally, for the more advanced developers, Candy Guards include a "route instruction," allowing fully customizable mint request routing through custom guard logic. -Creators can use what we call “**Guards**” to add various features to their Core Candy Machine. The Metaplex Core Candy Machine ships with an additional Solana Program called **Candy Guard** that ships with [**a total of 23 default guards**](/core-candy-machine/guards). By using an additional program, it allows advanced developers to fork the default Candy Guard program to create their own custom guards whilst still being able to rely on the main Candy Machine program. +To learn more about how to create your Custom Guard, follow this link: [Special Guard Instructions]() -Each guard can be enabled and configured at will so creators can pick and choose the features they need. Disabling all guards would be equivalent to allowing anyone to mint our NFTs for free at any time, which is likely not what we want. So let’s have a look at a few guards to create a more realistic example. +### Candy Groups -Say a Core Candy Machine has the following guards: +Candy Machine also supports `Guard Groups`, enabling multiple guard configuration with unique requirements that can operate simultaneously. This allows for different minting phases or behaviors within the same Candy Machine based on varying conditions. -- **Sol Payment**: This guard ensures the minting wallet has to pay a configured amount of SOL to a configured destination wallet. -- **Start Date**: This guard ensures minting can only start after the configured time. -- **Mint Limit**: This guard ensures each wallet cannot mint more than a configured amount. -- **Bot Tax**: This guard is a bit special. It doesn’t guard against anything but it changes the behaviour of a failed mint to prevent bots from minting Candy Machines. When this guard is activated, if any other activated guard fails to validate the mint, it will charge a small configured amount of SOL to the wallet that tried to mint. +To learn more about how to create Groups, follow this link: [Guard Groups]() -What we end up with is a bot-protected Candy Machine that charges SOL, launches at a specific time and only allows a limited amount of mints per wallet. Here’s a concrete example. +### Guard Example + +To create a bot-protected Candy Machine that charges SOL, launches at a specific time, and limits mints per wallet, configure the following guards: + +- **Sol Payment**: Requires the minting wallet to pay a configured amount of SOL to a destination wallet. +- **Start Date**: Allows minting only after a configured time. +- **Mint Limit**: Restricts each wallet from minting more than a set amount. +- **Bot Tax**: Penalizes failed mint attempts to deter bots by charging a small configured SOL fee to the minting wallet if any active guard blocks a mint. + +On-chain, this configuration would look like this: {% diagram %} {% node %} @@ -159,7 +172,4 @@ Bot tax charged {% edge from="mint-2" to="nft-2" path="bezier" /%} {% edge from="mint-3" to="fail-3" path="bezier" /%} {% edge from="mint-4" to="fail-4" path="bezier" /%} -{% /diagram %} - -As you can see, with more than 23 default guards and the ability to create custom guards, it enables creators to cherry-pick the features that matters to them and compose their perfect Candy Machine. This is such a powerful feature that we’ve dedicated many pages to it. The best place to start to know more about guards is the [Candy Guards](/core-candy-machine/guards) page. -Documents the latest changes. \ No newline at end of file +{% /diagram %} \ No newline at end of file diff --git a/src/pages/core-candy-machine/update.md b/src/pages/core-candy-machine/update.md index c1543e64..4a22ef34 100644 --- a/src/pages/core-candy-machine/update.md +++ b/src/pages/core-candy-machine/update.md @@ -4,6 +4,19 @@ metaTitle: Update a Core Candy Machine | Core Candy Machine description: Learn how to update your Core Candy Machine and it's various settings. --- +If the `isMutable` field was set to true when creating the Candy Machine, some data within the Candy Machine can be updated using the `updateCandyMachine()` function. + +Below is a breakdown of the arguments in the data structure that can be modified: + +| Attribute | Type | +|--------------------------|-------------------------------------| +| **itemsAvailable** | number | bigint | +| **isMutable** | boolean | +| **configLineSettings** | [Link](/core-candy-machine/create#with-config-line-settings) | +| **hiddenSettings** | [Link](/core-candy-machine/create#with-hidden-settings) | + +Here is an example of how to update a Core Candy Machine: + {% dialect-switcher title="Updating a Core Candy Machine" %} {% dialect title="JavaScript" id="js" %} @@ -12,7 +25,8 @@ import { updateCandyMachine } from '@metaplex-foundation/mpl-core-candy-machine' -const candyMachine = generateSigner(umi) +// Publickey of the candyMachine to update +const candyMachine = publicKey('11111111111111111111111111111111') await updateCandyMachine(umi, { candyMachine, @@ -28,57 +42,13 @@ await updateCandyMachine(umi, { {% /dialect %} {% /dialect-switcher %} -## Args +## Updating the Authority -{% dialect-switcher title="Update Core Candy Machine Args" %} -{% dialect title="JavaScript" id="js" %} - -Available arguments that can be passed into the updateCandyMachine function. - -| name | type | -| ------------ | --------- | -| candyMachine | publicKey | -| data | data | +To update the authority of the Candy Machine to a new address, use the `setMintAuthority()` function and pass the new address in the `mintAuthority` field. -{% /dialect %} -{% /dialect-switcher %} +Here's an example of how to update the authority of a Candy Machine: -Some settings are unabled to be changed/updated once minting has started. - -### data - -{% dialect-switcher title="Candy Machine Data Object" %} -{% dialect title="JavaScript" id="js" %} - -```ts -data = { - itemsAvailable: number | bigint; - isMutable: boolean; - configLineSettings: OptionOrNullable; - hiddenSettings: OptionOrNullable; -} -``` - -- [ConfigLineSettingsArgs](/core-candy-machine/create#config-line-settings) -- [HiddenSettingsArgs](/core-candy-machine/create#hidden-settings) - -{% /dialect %} -{% /dialect-switcher %} - -## Assigning a new Authority to the Candy Machine - -There may be scenarios where you may wish to transfer the Candy Machine authority across to a new address. This can be achieved with the `setMintAuthority` function. - -export declare type SetMintAuthorityInstructionAccounts = { -/** Candy Machine account. \*/ -candyMachine: PublicKey | Pda; -/** Candy Machine authority _/ -authority?: Signer; -/\*\* New candy machine authority _/ -mintAuthority: Signer; -}; - -{% dialect-switcher title="Assign New Authority to Core Candy Machine" %} +{% dialect-switcher title="Update Authority of Core Candy Machine" %} {% dialect title="JavaScript" id="js" %} ```ts @@ -96,27 +66,67 @@ await setMintAuthority(umi, { {% /dialect %} {% /dialect-switcher %} -When assigning a new Authority to a Core Candy Machine you will also have to update the Collection Asset to the same update Authority. - -## Updating guards - -Did you set something wrong in your guards? Did you change your mind about the mint price? Do you need to delay the start of the mint of a little? No worries, guards can easily be updated following the same settings used when creating them. - -You can enable new guards by providing their settings or disable current ones by giving them empty settings. - -{% dialect-switcher title="Update guards" %} +## Updating the Guards + +Updating the Guards, works similarly to the way we set them when we created the Candy Machine. To enable guards, provide their settings; to disable them, set them to none() or leave them out. + +**Note**: The entire guards object is replaced during the update, so include all guards you want to keep, even if their settings remain unchanged. Consider fetching the current guard settings before updating to avoid overwriting unintended fields. + +Here's a list of all the Candy Guards available and the individual attributes: + +{% totem %} + +{% totem-accordion title="Candy Guards Attributes" %} + +| Guard Name | Arguments | +|----------------------------|--------------------------------------------------------------------------| +| **addressGate** | { `address`: PublicKey } | +| **allocation** | { `id`: number, `limit`: number } | +| **allowList** | { `merkleRoot`: Uint8Array } | +| **assetBurn** | { `requiredCollection`: PublicKey } | +| **assetBurnMulti** | { `num`: number, `requiredCollection`: PublicKey } | +| **assetGate** | { `requiredCollection`: PublicKey } | +| **assetMintLimit** | { `id`: number, `limit`: number, `requiredCollection`: PublicKey } | +| **assetPayment** | { `destination`: PublicKey, `requiredCollection`: PublicKey } | +| **assetPaymentMulti** | { `destination`: PublicKey, `num`: number, `requiredCollection`: PublicKey } | +| **botTax** | { `lamports`: SolAmount, `lastInstruction`: boolean } | +| **edition** | { `editionStartOffset`: number } | +| **endDate** | { `date`: DateTimeInput } | +| **freezeSolPayment** | { `destination`: PublicKey, `lamports`: SolAmount } | +| **freezeTokenPayment** | { `amount`: number | bigint, `mint`: PublicKey, `destination`: PublicKey } | +| **gatekeeper** | { `expireOnUse`: boolean, `gatekeeperNetwork`: PublicKey } | +| **mintLimit** | { `id`: number, `limit`: number } | +| **nftBurn** | { `requiredCollection`: PublicKey } | +| **nftGate** | { `requiredCollection`: PublicKey } | +| **nftMintLimit** | { `id`: number, `limit`: number, `requiredCollection`: PublicKey } | +| **nftPayment** | { `destination`: PublicKey, `requiredCollection`: PublicKey } | +| **programGate** | { `additional`: PublicKey[] } | +| **redeemedAmount** | { `maximum`: number | bigint } | +| **solFixedFee** | { `destination`: PublicKey, `lamports`: SolAmount } | +| **solPayment** | { `lamports`: SolAmount, `destination`: PublicKey } | +| **startDate** | { `date`: DateTimeInput } | +| **thirdPartySigner** | { `signerKey`: PublicKey } | +| **token2022Payment** | { `amount`: number | bigint, `destinationAta`: PublicKey, `mint`: PublicKey } | +| **tokenBurn** | { `amount`: number | bigint, `mint`: PublicKey } | +| **tokenGate** | { `amount`: number | bigint, `mint`: PublicKey } | +| **tokenPayment** | { `amount`: number | bigint, `destinationAta`: PublicKey, `mint`: PublicKey } | +| **vanityMint** | { `regex`: string } | + + +{% /totem-accordion %} + +{% /totem %} + +Here is an example of updating the `guards` from an existing Candy Machine: + +{% dialect-switcher title="Update the Guards of a Core Candy Machine" %} {% dialect title="JavaScript" id="js" %} -You may update the guards of a Core Candy Machine the same way you created them. That is, by providing their settings inside the `guards` object of the `updateCandyGuard` function. Any guard set to `none()` or not provided will be disabled. - -Note that the entire `guards` object will be updated meaning **it will override all existing guards**! - -Therefore, make sure to provide the settings for all guards you want to enable, even if their settings are not changing. You may want to fetch the candy guard account first to fallback to its current guards. - -```tsx +```ts import { some, none, sol } from '@metaplex-foundation/umi' const candyGuard = await fetchCandyGuard(umi, candyMachine.mintAuthority) + await updateCandyGuard(umi, { candyGuard: candyGuard.publicKey, guards: { @@ -124,32 +134,23 @@ await updateCandyGuard(umi, { botTax: none(), solPayment: some({ lamports: sol(3), destination: treasury }), }, - groups: [ - // Either empty, or if you are using groups add the data here - ] }) ``` -API References: [updateCandyGuard](https://mpl-core-candy-machine.typedoc.metaplex.com/functions/updateCandyGuard.html), [CandyGuard](https://mpl-core-candy-machine.typedoc.metaplex.com/types/CandyGuard.html), [DefaultGuardSetArgs](https://mpl-core-candy-machine.typedoc.metaplex.com/types/DefaultGuardSetArgs.html) - {% /dialect %} {% /dialect-switcher %} -## Wrapping and unwrapping Candy Guard accounts manually +## Associating and Dissociating Guard accounts manually -So far we’ve managed both Core Candy Machine and Core Candy Guard accounts together because that makes the most sense for most projects. +The create function that we [used previously](/core-candy-machine/create) already takes care of creating and associating a brand new Candy Guard account for every Candy Machine account created. -However, it is important to note that Core Candy Machines and Core Candy Guards can be created and associated in different steps, even using our SDKs. +However, it is important to note that Core Candy Machines and Core Candy Guards can be created and associated in different steps by creating the two accounts separately and associate/dissociate them manually after using the `wrap()` and `unwrap()` function. -You will first need to create the two accounts separately and associate/dissociate them manually. +Here is an example of associating and dissociating the guards from an existing Candy Machine: {% dialect-switcher title="Associate and dissociate guards from a Candy Machine" %} {% dialect title="JavaScript" id="js" %} -The `create` function of the Umi library already takes care of creating and associating a brand new Candy Guard account for every Candy Machine account created. - -However, if you wanted to create them separately and manually associate/dissociate them, this is how you’d do it. - ```ts import { some, @@ -167,32 +168,19 @@ import { // Create a Candy Machine without a Candy Guard. const candyMachine = generateSigner(umi) + await createCandyMachine({ candyMachine, - tokenStandard: TokenStandard.NonFungible, - collectionMint: collectionMint.publicKey, + collection: collectionMint.publicKey, collectionUpdateAuthority: umi.identity, - itemsAvailable: 100, - sellerFeeBasisPoints: percentAmount(1.23), - creators: [ - { - address: umi.identity.publicKey, - verified: false, - percentageShare: 100 - }, - ], - configLineSettings: some({ - prefixName: 'My NFT #', - nameLength: 3, - prefixUri: 'https://example.com/', - uriLength: 20, - isSequential: false, - }), + itemsAvailable: 1000, + authority: umi.identity.publicKey, }).sendAndConfirm(umi) // Create a Candy Guard. const base = generateSigner(umi) const candyGuard = findCandyGuardPda(umi, { base: base.publicKey }) + await createCandyGuard({ base, guards: { @@ -215,7 +203,5 @@ await unwrap({ }).sendAndConfirm(umi) ``` -API References: [createCandyMachine](https://mpl-core-candy-machine.typedoc.metaplex.com/functions/createCandyMachine.html), [createCandyGuard](https://mpl-core-candy-machine.typedoc.metaplex.com/functions/createCandyGuard.html), [wrap](https://mpl-core-candy-machine.typedoc.metaplex.com/functions/wrap.html), [unwrap](https://mpl-core-candy-machine.typedoc.metaplex.com/functions/unwrap.html) - {% /dialect %} {% /dialect-switcher %} From ffe291086c9f6c33ca1c212dbe6241d5ff4af1d5 Mon Sep 17 00:00:00 2001 From: L0STE <125566964+L0STE@users.noreply.github.com> Date: Fri, 13 Dec 2024 20:04:01 +0100 Subject: [PATCH 3/6] Loading Items done --- src/pages/core-candy-machine/create.md | 4 +- src/pages/core-candy-machine/insert-items.md | 65 ++++++++------------ 2 files changed, 29 insertions(+), 40 deletions(-) diff --git a/src/pages/core-candy-machine/create.md b/src/pages/core-candy-machine/create.md index 814d81cc..08bdfadd 100644 --- a/src/pages/core-candy-machine/create.md +++ b/src/pages/core-candy-machine/create.md @@ -95,9 +95,9 @@ const createIx = await create(umi, { // ... configLineSettings: some({ prefixName: 'Example Asset #', - nameLength: 15, + nameLength: 4, prefixUri: 'https://example.com/metadata/', - uriLength: 29, + uriLength: 9, isSequential: false, }), }) diff --git a/src/pages/core-candy-machine/insert-items.md b/src/pages/core-candy-machine/insert-items.md index 760695b5..38a6c6c3 100644 --- a/src/pages/core-candy-machine/insert-items.md +++ b/src/pages/core-candy-machine/insert-items.md @@ -1,23 +1,29 @@ --- -title: Inserting Items -metaTitle: Inserting Items | Core Candy Machine +title: Loading Items +metaTitle: Loading Items | Core Candy Machine description: How to load Core NFT Assets into a Core Candy Machine. --- -Now that we have a name and URI for all of our items, all we need to do is insert them into our Core Candy Machine account. +After [preparing the Candy Machine Assets](/core-candy-machine/guides/preparing-assets), the next step is to insert them into the Candy Machine. This is extremely important because **minting will not be permitted until all items have been inserted**. -This is an important part of the process and, when using Config Line Settings, **minting will not be permitted until all items have been inserted**. +**Note**: Solana transactions have size limits, this restrict the number of items that can be inserted per transaction based on the length of asset names and URIs. Shorter names and URIs allow more items to fit into a single transaction. -Note that the name and URI of each inserted item are respectively constraint by the **Name Length** and **URI Length** attributes of the Config Line Settings. +## Loading Items in the Candy Machine -Additionally, because transactions are limited to a certain size, we cannot insert thousands of items within the same transaction. The number of items we can insert per transaction will depend on the **Name Length** and **URI Length** attributes defined in the Config Line Settings. The shorter our names and URIs are, the more we'll be able to fit into a transaction. +You can use the `addConfigLines()` function to load items into the Candy Machine. You need to specify the configLines to insert and the index where they should be added. -{% dialect-switcher title="Add config lines" %} -{% dialect title="JavaScript" id="js" %} +Here's an example of how to do it: -When using the Umi library, you may use the `addConfigLines` function to insert items into a Core Candy Machine. It requires the config lines to add as well as the index in which you want to insert them. +{% dialect-switcher title="Loading Items in the Candy Machine" %} +{% dialect title="JavaScript" id="js" %} ```ts +import { publicKey } from "@metaplex-foundation/umi"; +import { fetchCandyMachine, addConfigLines } from "@metaplex-foundation/mpl-core-candy-machine"; + +const candyMachineId = "11111111111111111111111111111111" +const candyMachine = await fetchCandyMachine( umi, publicKey(candyMachineId)) + await addConfigLines(umi, { candyMachine: candyMachine.publicKey, index: 0, @@ -41,24 +47,19 @@ await addConfigLines(umi, { ], }).sendAndConfirm(umi) ``` - -API References: [addConfigLines](https://mpl-core-candy-machine.typedoc.metaplex.com/functions/addConfigLines.html) - {% /dialect %} {% /dialect-switcher %} -## Inserting Items Using Prefixes - -When using name and/or URI prefixes, you only need to insert the part that comes after them. +### that uses Config Line Settings -Note that, since using prefixes can significantly reduce the Name Length and URI Length, it should help you fit a lot more items per transaction. +By setting up the [Config Line Settings](/core-candy-machine/create#with-config-line-settings), you only need to insert the part that comes after the prefixes that we set up on creation. Using this setup, significantly reduce the Name Length and URI Length helping you fit a lot more items per transaction. -{% dialect-switcher title="Add config lines from a given index" %} -{% dialect title="JavaScript" id="js" %} +**Note**: name and URI of each inserted item are respectively constraint by the **Name Length** and **URI Length** attributes of the Config Line Settings. -When adding config lines to a Core Candy Machine that uses prefixes, you may only provide the part of the name and URI that comes after the prefix when using the `addConfigLines` function. +The way to do it is the same, it's just much shorter to do, here's an example of it -For instance, say you had a Core Candy Machine with the following config line settings. +{% dialect-switcher title="Loading Items in the Candy Machine" %} +{% dialect title="JavaScript" id="js" %} ```ts await create(umi, { @@ -71,14 +72,10 @@ await create(umi, { isSequential: false, }), }).sendAndConfirm(umi) -``` -Then, you can insert config lines like so. - -```ts await addConfigLines(umi, { candyMachine: candyMachine.publicKey, - index: candyMachine.itemsLoaded, + index: 0, configLines: [ { name: '1', uri: '1.json' }, { name: '2', uri: '2.json' }, @@ -87,19 +84,17 @@ await addConfigLines(umi, { }).sendAndConfirm(umi) ``` -API References: [addConfigLines](https://mpl-core-candy-machine.typedoc.metaplex.com/functions/addConfigLines.html) - {% /dialect %} {% /dialect-switcher %} -## Overriding Existing Items +## Overriding Existing Items in the Candy Machine -When inserting items, you may provide the position in which these items should be inserted. This enables you to insert items in any order you want but also allows you to update items that have already been inserted. +Since the `addConfigLines()` function requires an index, it can be used not only for inserting new items but also for updating items that have already been inserted. -{% dialect-switcher title="Override config lines" %} -{% dialect title="JavaScript" id="js" %} +Here's a showcase of this behaviour: -The following examples show how you can insert three items and, later on, update the second item inserted. +{% dialect-switcher title="Overriding Existing Items in the Candy Machine " %} +{% dialect title="JavaScript" id="js" %} ```ts await addConfigLines(umi, { @@ -124,11 +119,5 @@ candyMachine.items[1].name // "My Asset #X" candyMachine.items[2].name // "My Asset #3" ``` -API References: [addConfigLines](https://mpl-core-candy-machine.typedoc.metaplex.com/functions/addConfigLines.html) - {% /dialect %} {% /dialect-switcher %} - -## Conclusion - -And just like that, we have a loaded Core Candy Machine ready to mint Assets! However, we've not created any requirements for our minting process. How can we configure the price of the mint? How can we ensure that buyers are holders of a specific token or an Asset from a specific collection? How can we set the start date of our mint? What about the end conditions? From bbfbdf8acc9f4d3a83d26173942b839060005e8b Mon Sep 17 00:00:00 2001 From: L0STE <125566964+L0STE@users.noreply.github.com> Date: Mon, 16 Dec 2024 18:33:15 +0100 Subject: [PATCH 4/6] Updated the `update` paragraph and reworked the `withdraw` paragraph as well --- src/pages/core-candy-machine/insert-items.md | 2 +- src/pages/core-candy-machine/mint.md | 10 +++++-- src/pages/core-candy-machine/update.md | 30 +++++++++++++++++-- .../withdrawing-a-candy-machine.md | 12 ++++---- 4 files changed, 43 insertions(+), 11 deletions(-) diff --git a/src/pages/core-candy-machine/insert-items.md b/src/pages/core-candy-machine/insert-items.md index 38a6c6c3..d05209ad 100644 --- a/src/pages/core-candy-machine/insert-items.md +++ b/src/pages/core-candy-machine/insert-items.md @@ -1,5 +1,5 @@ --- -title: Loading Items +title: Loading Items in the Candy Machine metaTitle: Loading Items | Core Candy Machine description: How to load Core NFT Assets into a Core Candy Machine. --- diff --git a/src/pages/core-candy-machine/mint.md b/src/pages/core-candy-machine/mint.md index 5a97b8b5..d212aa05 100644 --- a/src/pages/core-candy-machine/mint.md +++ b/src/pages/core-candy-machine/mint.md @@ -1,12 +1,16 @@ --- -title: Minting +title: Minting Assets from a Candy Machine metaTitle: Minting | Core Candy Machine description: How to mint from a Core Candy Machine allowing users to purchase your Core NFT Assets. --- -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! {% .lead %} +**Note**: Minting can only begin after all assets have been loaded into the Candy Machine. If you missed this step, refer to [Loading Items in the Candy Machine](/core-candy-machine/insert-items) -## Basic Minting +## Minting Assets from a Candy Machine + +There are different way to mint Assets from the Candy Machine: +- From the Candy Machine Program: only the authority can mint from it and, therefore, it will need to sign the transaction +- From the Candy Guard Program: As mentioned [in the Candy Guards page](/core-candy-machine/guards#why-another-program), 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. diff --git a/src/pages/core-candy-machine/update.md b/src/pages/core-candy-machine/update.md index 4a22ef34..ea5ca84c 100644 --- a/src/pages/core-candy-machine/update.md +++ b/src/pages/core-candy-machine/update.md @@ -4,7 +4,7 @@ metaTitle: Update a Core Candy Machine | Core Candy Machine description: Learn how to update your Core Candy Machine and it's various settings. --- -If the `isMutable` field was set to true when creating the Candy Machine, some data within the Candy Machine can be updated using the `updateCandyMachine()` function. +## Updating the Data Below is a breakdown of the arguments in the data structure that can be modified: @@ -44,7 +44,7 @@ await updateCandyMachine(umi, { ## Updating the Authority -To update the authority of the Candy Machine to a new address, use the `setMintAuthority()` function and pass the new address in the `mintAuthority` field. +To update the authority of the Candy Machine to a new address, use the `setCandyMachineAuthority()` function and pass the new address in the `newAuthority` field. Here's an example of how to update the authority of a Candy Machine: @@ -66,6 +66,32 @@ await setMintAuthority(umi, { {% /dialect %} {% /dialect-switcher %} +## Updating the Mint Authority + +To update the mint authority of the Candy Machine to a new address, use the `setMintAuthority()` function and pass the new address in the `mintAuthority` field. + +**Note**: If the Candy Machine has any guards, the `mintAuthority` field will be assigned to that account. By changing the mintAuthority, you're `disabling` the Candy Guard mechanism. + +Here's an example of how to update the mint authority of a Candy Machine: + +{% dialect-switcher title="Update Mint Authority of Core Candy Machine" %} +{% dialect title="JavaScript" id="js" %} + +```ts +import { setMintAuthority } from '@metaplex-foundation/mpl-core-candy-machine' + +const candyMachine = publicKey('11111111111111111111111111111111') +const newAuthority = publicKey('22222222222222222222222222222222') + +await setMintAuthority(umi, { + candyMachine, + mintAuthority: newAuthority, +}).sendAndConfirm(umi) +``` + +{% /dialect %} +{% /dialect-switcher %} + ## Updating the Guards Updating the Guards, works similarly to the way we set them when we created the Candy Machine. To enable guards, provide their settings; to disable them, set them to none() or leave them out. diff --git a/src/pages/core-candy-machine/withdrawing-a-candy-machine.md b/src/pages/core-candy-machine/withdrawing-a-candy-machine.md index bb67b9e3..e730a78f 100644 --- a/src/pages/core-candy-machine/withdrawing-a-candy-machine.md +++ b/src/pages/core-candy-machine/withdrawing-a-candy-machine.md @@ -1,14 +1,16 @@ --- -title: Withdrawing a Core Candy Machine +title: Withdrawing a Candy Machine metaTitle: Withdrawing a Core Candy Machine | Core Candy Machine description: How to withdraw a Core Candy Machine and claim back rent from it. --- -The withdrawing of a Core Candy Machine returns all the on chain storage rent cost of the Candy Machine while subsequently deleting the data and making the Candy Machine unusable. +**Note**: This is an **IRREVERSIBLE** action. Since there is no way to reinstate/recover a Candy Machine after this action, you should look at withdrawing from the Candy Machine only if the minting process is 100% done. -{% callout %} -This operation is irreversible so only withdraw your Core Candy Machine when you are 100% finished with the minting process. Your Core Candy Machine can not be reinstated or recovered. -{% /callout %} +## Withdrawing a Candy Machine + +Withdrawing a Candy Machine means deleting all its onchain data and retrieving the rent cost making the account effectively unusable. + +**Note**: Note: This process applies to all types of Candy Machines (with Config Line Settings, Hidden Settings, and Guards). However, if your Candy Machine has an associated Candy Guard, this instruction will not withdraw the rent from that as well. To learn how to withdraw a Candy Guard, refer to this [paragraph](). {% dialect-switcher title="Withdraw a Core Candy Machine" %} {% dialect title="JavaScript" id="js" %} From fa399801d8b2fb9cb68bd96aac5e7ca0e6227b8c Mon Sep 17 00:00:00 2001 From: L0STE <125566964+L0STE@users.noreply.github.com> Date: Tue, 17 Dec 2024 00:05:43 +0100 Subject: [PATCH 5/6] Finished refactoring Mint and Fetch --- .../fetching-a-candy-machine.md | 67 ++- src/pages/core-candy-machine/mint.md | 447 ++++-------------- src/pages/core-candy-machine/update.md | 2 +- .../withdrawing-a-candy-machine.md | 2 + 4 files changed, 148 insertions(+), 370 deletions(-) diff --git a/src/pages/core-candy-machine/fetching-a-candy-machine.md b/src/pages/core-candy-machine/fetching-a-candy-machine.md index 5c25b150..f6e83a93 100644 --- a/src/pages/core-candy-machine/fetching-a-candy-machine.md +++ b/src/pages/core-candy-machine/fetching-a-candy-machine.md @@ -4,27 +4,76 @@ metaTitle: Fetching a Core Candy Machine | Core Candy Machine description: How to fetch the data of a Core Core Candy Machine from the Solana blockchain. --- -Fetching a Core Candy Machine and its data can be achieved as follows: +You can fetch a Core Candy Machine and its data using the `fetchCandyMachine()` function. The response will contain the following arguments: + +| **Name** | **Type** | **Description** | +|-------------------|---------------------------|------------------------------------------------------------------------------------------------| +| `authority` | `PublicKey` | The key responsible for updating the Candy Machine's data. | +| `mintAuthority` | `PublicKey` | The key responsible for minting NFTs from the Candy Machine. | +| `collectionMint` | `PublicKey` | The address of the NFT collection associated with the Candy Machine. | +| `itemsRedeemed` | `bigint` | The number of items successfully minted from the Candy Machine. | +| `data` | `CandyMachineData` | Contains the Candy Machine's configuration and settings. | +| `items` | `CandyMachineItem[]` | Represents items available for minting in the Candy Machine. | +| `itemsLoaded` | `number` | The total number of items currently loaded into the Candy Machine. | +| `isMutable` | `boolean` | Indicates whether assets created by the Candy Machine can be modified after creation. | + +And this are the `CandyMachineData` and `CandyMachineItem` types: + +{% totem %} + +{% totem-accordion title="`CandyMachineItem` type" %} + +```ts +export declare type CandyMachineItem = { + /** The index of the config line. */ + readonly index: number; + /** Whether the item has been minted or not. */ + readonly minted: boolean; + /** The name of the NFT to be. */ + readonly name: string; + /** The URI of the NFT to be, pointing to some off-chain JSON Metadata. */ + readonly uri: string; +}; +``` + +{% /totem-accordion %} + +{% totem-accordion title="`CandyMachineData` type" %} + +```ts +export declare type CandyMachineData = { + /** Number of assets available */ + itemsAvailable: bigint; + /** Max supply of each individual asset (default 0) */ + maxEditionSupply: bigint; + /** Indicates if the asset is mutable or not (default yes) */ + isMutable: boolean; + /** Config line settings */ + configLineSettings: Option; + /** Hidden setttings */ + hiddenSettings: Option; +}; +``` + +{% /totem-accordion %} + +{% /totem %} + +Here is an example of how to fetch a Core Candy Machine directly: {% dialect-switcher title="Fetch a Core Candy Machine" %} {% dialect title="JavaScript" id="js" %} ```ts -import { fetchCandyMachine, mplCandyMachine as mplCoreCandyMachine } from "@metaplex-foundation/mpl-core-candy-machine"; +import { fetchCandyMachine, mplCandyMachine } from "@metaplex-foundation/mpl-core-candy-machine"; import { publicKey } from "@metaplex-foundation/umi"; import { createUmi } from "@metaplex-foundation/umi-bundle-defaults"; -const mainnet = 'https://api.mainnet-beta.solana.com' -const devnet = 'https://api.devnet.solana.com' - -const umi = createUmi(mainnet) -.use(mplCoreCandyMachine()) +const umi = createUmi("https://api.devnet.solana.com").use(mplCandyMachine()) const candyMachineId = "11111111111111111111111111111111" const candyMachine = await fetchCandyMachine( umi, publicKey(candyMachineId)); - -console.log({ candyMachine }); ``` {% /dialect %} diff --git a/src/pages/core-candy-machine/mint.md b/src/pages/core-candy-machine/mint.md index d212aa05..a8560482 100644 --- a/src/pages/core-candy-machine/mint.md +++ b/src/pages/core-candy-machine/mint.md @@ -8,120 +8,15 @@ description: How to mint from a Core Candy Machine allowing users to purchase yo ## Minting Assets from a Candy Machine -There are different way to mint Assets from the Candy Machine: -- From the Candy Machine Program: only the authority can mint from it and, therefore, it will need to sign the transaction -- From the Candy Guard Program: +When the Candy Machine has no guards, only the `mintAuthority` can mint from it. This can be done using the `mintAssetFromCandyMachine()` instruction while explicitly specifying who will receive the asset (`assetOwner`). -As mentioned [in the Candy Guards page](/core-candy-machine/guards#why-another-program), 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 Core 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. - -{% diagram %} - -{% node %} -{% node #candy-machine-1 label="Core Candy Machine" theme="blue" /%} -{% node label="Owner: Core Candy Machine Core Program" theme="dimmed" /%} -{% node label="Features" /%} -{% node label="Authority" /%} -{% node #mint-authority-1 %} - -Mint Authority = Candy Guard {% .font-semibold %} - -{% /node %} -{% node label="..." /%} -{% /node %} - -{% node parent="candy-machine-1" y=160 x=20 %} -{% node #candy-guard-1 label="Candy Guard" theme="blue" /%} -{% node label="Owner: Candy Guard Program" theme="dimmed" /%} -{% node label="Guards" theme="mint" z=1 /%} -{% node label="Sol Payment" /%} -{% node label="Token Payment" /%} -{% node label="Start Date" /%} -{% node label="End Date" /%} -{% node label="..." /%} -{% /node %} - -{% node parent="candy-machine-1" x=350 %} -{% node #mint-1 label="Mint" theme="pink" /%} -{% node label="Candy Guard Program" theme="pink" /%} -{% /node %} -{% node parent="mint-1" x=45 y=-20 label="Access Control" theme="transparent" /%} -{% node parent="mint-1" x=-120 y=-35 theme="transparent" %} -Anyone can mint as long \ -as they comply with the \ -activated guards. -{% /node %} - -{% node parent="mint-1" x=-36 y=100 %} -{% node #mint-2 label="Mint" theme="pink" /%} -{% node label="Core Candy Machine Core Program" theme="pink" /%} -{% /node %} -{% node parent="mint-2" x=120 y=-20 label="Mint Logic" theme="transparent" /%} -{% node parent="mint-2" x=200 y=-18 theme="transparent" %} -Only Alice \ -can mint. -{% /node %} - -{% node #nft parent="mint-2" x=77 y=100 label="NFT" /%} - -{% node parent="mint-2" x=280 %} -{% node #candy-machine-2 label="Core Candy Machine" theme="blue" /%} -{% node label="Owner: Core Candy Machine Core Program" theme="dimmed" /%} -{% node label="Features" /%} -{% node label="Authority" /%} -{% node #mint-authority-2 %} - -Mint Authority = Alice {% .font-semibold %} - -{% /node %} -{% node label="..." /%} -{% /node %} - -{% edge from="candy-guard-1" to="mint-authority-1" fromPosition="left" toPosition="left" arrow=false dashed=true /%} -{% edge from="mint-1" to="mint-2" theme="pink" path="straight" /%} -{% edge from="mint-2" to="nft" theme="pink" path="straight" /%} -{% edge from="candy-machine-1" to="mint-1" theme="pink" /%} -{% edge from="candy-guard-1" to="mint-1" theme="pink" /%} -{% edge from="candy-machine-2" to="mint-2" theme="pink" path="straight" /%} - -{% /diagram %} - -If everything went well, an NFT will be created following the parameters configured in the Core Candy Machine. For instance, if the given Core 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. +Here is an example of how to mint from a Core Candy Machine directly: {% dialect-switcher title="Mint from a Core Candy Machine" %} {% dialect title="JavaScript" id="js" %} -To mint from a Core Candy Machine via a configured Candy Guard account, you may use the `mintV1` 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. - -```ts -import { mintV1 } from "@metaplex-foundation/mpl-core-candy-machine"; -import { setComputeUnitLimit } from "@metaplex-foundation/mpl-toolbox"; -import { generateSigner } from "@metaplex-foundation/umi"; - -const candyMachineId = publicKey("11111111111111111111111111111111"); -const coreCollection = publicKey("22222222222222222222222222222222"); -const asset = generateSigner(umi); - -await mintV1(umi, { - candyMachine: candyMachineId, - asset, - collection: coreCollection, -}).sendAndConfirm(umi); - -``` - -In the rare event that you wish to mint directly from the Core Candy Machine program instead of the Candy Guard Program, you may use the `mintAssetFromCandyMachine` function instead. This function requires the mint authority of the Core Candy Machine to be provided as a signer and accepts an explicit `assetOwner` attribute. - ```ts -import { mintFromCandyMachineV2 } from '@metaplex-foundation/mpl-core-candy-machine' -import { setComputeUnitLimit } from '@metaplex-foundation/mpl-toolbox' +import { mintAssetFromCandyMachine } from '@metaplex-foundation/mpl-core-candy-machine' import { transactionBuilder, generateSigner } from '@metaplex-foundation/umi' const candyMachineId = publicKey('11111111111111111111111111111111') @@ -137,300 +32,144 @@ await mintAssetFromCandyMachine(umi, { }).sendAndConfirm(umi); ``` -API References: [mintV1](https://mpl-core-candy-machine.typedoc.metaplex.com/functions/mintV1.html), [mintAssetFromCandyMachine](https://mpl-core-candy-machine.typedoc.metaplex.com/functions/mintAssetFromCandyMachine.html) - {% /dialect %} {% /dialect-switcher %} -## Minting With Guards +### with guards -When minting from a Core Candy Machine that uses a bunch of guards, you may need to provide additional guard-specific information. +When a Candy Machine has guards, its `mintAuthority` is transferred to the associated Candy Guard account. This ensures that all configured rules are enforced before minting, which is why we're using a different instruction (`mintV1`). -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. +Depending on the guards configured in the Candy Guard account, additional guard-specific parameters and accounts may be required for the minting process. Below is a list of the extra parameters that may be needed for each guard: -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. +{% totem %} -{% diagram %} +{% totem-accordion title="Candy Guards Mint Arguments" %} -{% node %} -{% node #candy-machine-1 label="Core Candy Machine" theme="blue" /%} -{% node label="Owner: Core Candy Machine Core Program" theme="dimmed" /%} -{% /node %} +| **Guard Name** | **Arguments** | +|------------------------------|--------------------------------------------------------| +| **AllocationMintArgs** | { `id`: number } | +| **AllowList** | { `merkleRoot`: Uint8Array } | +| **AssetBurnMintArgs** | { `asset`: PublicKey, `requiredCollection`: PublicKey } | +| **AssetBurnMultiMintArgs** | { `assets`: PublicKey[], `requiredCollection`: PublicKey } | +| **AssetGateMintArgs** | { `asset`: PublicKey } | +| **AssetMintLimitMintArgs** | { `asset`: PublicKey, `id`: number } | +| **AssetPaymentMintArgs** | { `asset`: PublicKey, `destination`: PublicKey, `requiredCollection`: PublicKey } | +| **AssetPaymentMultiMintArgs**| { `assets`: PublicKey[], `destination`: PublicKey, `requiredCollection`: PublicKey } | +| **FreezeSolPayment** | { `destination`: PublicKey, `lamports`: SolAmount } | +| **FreezeTokenPaymentArgs** | { `amount`: number | bigint, `destinationAta`: PublicKey, `mint`: PublicKey } | +| **GatekeeperMintArgs** | { `expireOnUse`: boolean, `gatekeeperNetwork`: PublicKey, `tokenAccount?`: PublicKey } | +| **MintLimitMintArgs** | { `id`: number } | +| **NftBurnMintArgs** | { `mint`: PublicKey, `requiredCollection`: PublicKey, `tokenAccount?`: PublicKey, `tokenStandard`: TokenStandard } | +| **NftGateMintArgs** | { `mint`: PublicKey, `tokenAccount?`: PublicKey } | +| **NftMintLimitMintArgs** | { `id`: number, `mint`: PublicKey, `tokenAccount?`: PublicKey } | +| **NftPaymentMintArgs** | { `destination`: PublicKey, `mint`: PublicKey, `ruleSet?`: PublicKey, `tokenAccount?`: PublicKey, `tokenStandard`: TokenStandard } | +| **SolFixedFeeMintArgs** | { `destination`: PublicKey } | +| **SolPaymentMintArgs** | { `destination`: PublicKey } | +| **ThirdPartySignerMintArgs** | { `signer`: Signer } | +| **Token2022PaymentMintArgs** | { `destinationAta`: PublicKey, `mint`: PublicKey } | +| **TokenBurnMintArgs** | { `mint`: PublicKey } | +| **TokenGateMintArgs** | { `mint`: PublicKey } | +| **TokenPaymentMintArgs** | { `destinationAta`: PublicKey, `mint`: PublicKey } | -{% node parent="candy-machine-1" y=80 x=20 %} -{% node #candy-guard-1 label="Candy Guard" theme="blue" /%} -{% node label="Owner: Candy Guard Program" theme="dimmed" /%} -{% node label="Guards" theme="mint" z=1 /%} -{% node #nft-payment-guard label="NFT Payment" /%} -{% node label="Token Payment" /%} -{% node label="Start Date" /%} -{% node #third-party-signer-guard label="Third Party Signer" /%} -{% node label="..." /%} -{% /node %} +{% /totem-accordion %} -{% node parent="candy-machine-1" x=700 %} -{% node #mint-1 label="Mint" theme="pink" /%} -{% node label="Candy Guard Program" theme="pink" /%} -{% /node %} -{% node parent="mint-1" x=45 y=-20 label="Access Control" theme="transparent" /%} - -{% node parent="mint-1" x=-22 y=100 %} -{% node #mint-2 label="Mint" theme="pink" /%} -{% node label="Core Candy Machine Core Program" theme="pink" /%} -{% /node %} -{% node parent="mint-2" x=120 y=-20 label="Mint Logic" theme="transparent" /%} +{% /totem %} -{% node #nft parent="mint-2" x=62 y=100 label="NFT" /%} - -{% node parent="mint-2" x=-400 %} -{% node #mint-settings label="Mint Settings" /%} -{% node label="Using our SDKs" theme="dimmed" /%} -{% /node %} +**Note**: Due to the extra parameters and data required by the transaction, adding more Candy Guards will increase the need for additional compute units. -{% node #mint-args label="Mint Arguments" parent="mint-settings" x=100 y=80 theme="slate" /%} -{% node #mint-accounts label="Mint Remaining Accounts" parent="mint-args" y=50 theme="slate" /%} - -{% edge from="candy-guard-1" to="candy-machine-1" fromPosition="left" toPosition="left" arrow=false /%} -{% edge from="mint-1" to="mint-2" theme="pink" path="straight" /%} -{% edge from="mint-2" to="nft" theme="pink" path="straight" /%} -{% edge from="candy-machine-1" to="mint-1" theme="pink" /%} -{% edge from="nft-payment-guard" to="mint-settings" theme="slate" /%} -{% edge from="third-party-signer-guard" to="mint-settings" theme="slate" /%} -{% edge from="mint-settings" to="mint-args" theme="slate" fromPosition="bottom" /%} -{% edge from="mint-settings" to="mint-accounts" theme="slate" fromPosition="bottom" /%} -{% edge from="mint-args" to="mint-1" theme="pink" /%} -{% edge from="mint-accounts" to="mint-1" theme="pink" /%} - -{% /diagram %} - -[Each available guard](/core-candy-machine/guards) 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. - -Please note that you may need to increase the number of computer units depending on the number of candy guards you've created the core candy machine with to ensure the transaction is successful. Our SDKs may also help with this. +Here is an example of how to mint from a Core Candy Machine with Guards that requires additional paramters: {% dialect-switcher title="Mint from a Core Candy Machine with guards" %} {% dialect title="JavaScript" id="js" %} -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 Core Candy Machine. - -As mentioned above, you may need to increase the compute unit limit of the transaction to ensure the `mintV1` instruction is successful. Current units are set to `300_000` but you can adjust this number as you see fit. You may do this by using the `setComputeUnitLimit` helper function on the `mpl-toolbox` Umi library as illustrated in the code snippet below. - ```ts import { some, generateSigner, - transactionBuilder, } from '@metaplex-foundation/umi' -import { create, mintV1 } from '@metaplex-foundation/mpl-core-candy-machine' -import { setComputeUnitLimit } from '@metaplex-foundation/mpl-toolbox' - -// Create a Core Candy Machine with guards. -const thirdPartySigner = generateSigner() -await create(umi, { - // ... - guards: { - thirdPartySigner: some({ signer: thirdPartySigner.publicKey }), - mintLimit: some({ id: 1, limit: 3 }), +import { mintV1 } from '@metaplex-foundation/mpl-core-candy-machine' + +const candyMachineId = publicKey('11111111111111111111111111111111') +const coreCollection = publicKey('22222222222222222222222222222222') +const asset = generateSigner(umi) + +await mintV1(umi, { + candyMachine: candyMachineId, + asset, + collection: coreCollection, + mintArgs: { + thirdPartySigner: some({ signer: thirdPartySigner }), + mintLimit: some({ id: 1 }), }, }).sendAndConfirm(umi) - -// Mint from the Core Candy Machine. -const nftMint = generateSigner(umi) -await transactionBuilder() - .add(setComputeUnitLimit(umi, { units: 300_000 })) - .add( - mintV1(umi, { - candyMachine: candyMachineId, - asset, - collection: coreCollection, - mintArgs: { - thirdPartySigner: some({ signer: thirdPartySigner }), - mintLimit: some({ id: 1 }), - }, - }) - ) - .sendAndConfirm(umi) ``` -API References: [mintV1](https://mpl-core-candy-machine.typedoc.metaplex.com/functions/mintV1.html), [DefaultGuardSetMintArgs](https://mpl-core-candy-machine.typedoc.metaplex.com/types/DefaultGuardSetMintArgs.html) - {% /dialect %} {% /dialect-switcher %} -## Minting With Guard Groups +### with guard groups -When minting from a Core Candy Machine using guard groups, **we must explicitly select which group we want to mint from** by providing its label. +When a Candy Machine has guard groups, same as [minting with guards](#with-guards) its `mintAuthority` is transferred to the associated Candy Guard account and depending on the guards, additional guard-specific parameters and accounts may be required for the minting process. -Additionally, Mint Settings may also be required as explained in [the previous section](#minting-with-guards). However, **the Mint Settings will apply to the “Resolved Guards” of the selected group**. +The main difference between the two types is that when using guard groups, **we must explicitly select which group we want to mint from** by providing its label. Additionally the guard-specific parameters that needs to be added are specific to the choosen group. -For instance, imagine a Core Candy Machine with the following guards: +For example, for 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 +- **Default Guards**: Bot Tax, Third Party Signer, Start Date +- **Group 1 - Label: nft**: NFT Payment, Start Date +- **Group 2 - Label: public**: Sol Payment -The Resolved Guards of Group 1 — labelled “nft” — are: +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. +Therefore, the guard-specific parameters must be related only to these Resolved Guards. -{% diagram %} - -{% node %} -{% node #candy-machine-1 label="Core Candy Machine" theme="blue" /%} -{% node label="Owner: Core Candy Machine Core Program" theme="dimmed" /%} -{% /node %} - -{% node parent="candy-machine-1" y=80 x=20 %} -{% node #candy-guard-1 label="Candy Guard" theme="blue" /%} -{% node label="Owner: Candy Guard Program" theme="dimmed" /%} -{% node label="Guards (default guards)" theme="mint" z=1 /%} -{% node label="Bot Tax" /%} -{% node #third-party-signer-guard label="Third Party Signer" /%} -{% node label="Start Date" /%} -{% node #nft-group theme="mint" z=1 %} -Group 1: "nft" {% .font-semibold %} -{% /node %} -{% node #nft-payment-guard label="NFT Payment" /%} -{% node label="Start Date" /%} -{% node theme="mint" z=1 %} -Group 2: "public" -{% /node %} -{% node label="SOL Payment" /%} -{% /node %} - -{% node parent="candy-machine-1" x=700 %} -{% node #mint-1 label="Mint" theme="pink" /%} -{% node label="Candy Guard Program" theme="pink" /%} -{% /node %} -{% node parent="mint-1" x=45 y=-20 label="Access Control" theme="transparent" /%} - -{% node parent="mint-1" x=-22 y=100 %} -{% node #mint-2 label="Mint" theme="pink" /%} -{% node label="Core Candy Machine Core Program" theme="pink" /%} -{% /node %} -{% node parent="mint-2" x=120 y=-20 label="Mint Logic" theme="transparent" /%} - -{% node #nft parent="mint-2" x=62 y=100 label="NFT" /%} - -{% node parent="mint-2" x=-400 y=60 %} -{% node #mint-settings label="Mint Settings" /%} -{% node label="Using our SDKs" theme="dimmed" /%} -{% /node %} - -{% node #mint-args label="Mint Arguments" parent="mint-settings" x=100 y=80 theme="slate" /%} -{% node #mint-accounts label="Mint Remaining Accounts" parent="mint-args" y=50 theme="slate" /%} - -{% edge from="candy-guard-1" to="candy-machine-1" fromPosition="left" toPosition="left" arrow=false /%} -{% edge from="mint-1" to="mint-2" theme="pink" path="straight" /%} -{% edge from="mint-2" to="nft" theme="pink" path="straight" /%} -{% edge from="candy-machine-1" to="mint-1" theme="pink" /%} -{% edge from="nft-payment-guard" to="mint-settings" theme="slate" /%} -{% edge from="third-party-signer-guard" to="mint-settings" theme="slate" /%} -{% edge from="mint-settings" to="mint-args" theme="slate" fromPosition="bottom" /%} -{% edge from="mint-settings" to="mint-accounts" theme="slate" fromPosition="bottom" /%} -{% edge from="mint-args" to="mint-1" theme="pink" /%} -{% edge from="mint-accounts" to="mint-1" theme="pink" /%} -{% edge from="nft-group" to="mint-1" theme="pink" /%} - -{% /diagram %} - -{% seperator h="6" /%} +Here is an example of how to mint from a Core Candy Machine with guard groups that requires additional paramters: {% dialect-switcher title="Mint from a Core Candy Machine with guard groups" %} {% dialect title="JavaScript" id="js" %} -When minting from a Core 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 Core Candy Machine described above. - ```ts -// Create a Core 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 Core Candy Machine. +import { + some, + generateSigner, +} from '@metaplex-foundation/umi' +import { mintV1 } from '@metaplex-foundation/mpl-core-candy-machine' const candyMachineId = publicKey('11111111111111111111111111111111') const coreCollection = publicKey('22222222222222222222222222222222') const asset = generateSigner(umi) -await transactionBuilder() - .add(setComputeUnitLimit(umi, { units: 300_000 })) - .add( - mintV1(umi, { - candyMachine: candyMachineId, - asset, - collection: coreCollection, - group: some('nft'), - mintArgs: { - thirdPartySigner: some({ signer: thirdPartySigner }), - nftPayment: some({ - mint: nftFromRequiredCollection.publicKey, - destination: nftTreasury, - tokenStandard: TokenStandard.NonFungible, - }), - }, - }) - ) - .sendAndConfirm(umi) +await mintV1(umi, { + candyMachine: candyMachineId, + asset, + collection: coreCollection, + group: some('nft'), + mintArgs: { + thirdPartySigner: some({ signer: thirdPartySigner }), + nftPayment: some({ + mint: nftFromRequiredCollection.publicKey, + destination: nftTreasury, + tokenStandard: TokenStandard.NonFungible, + }), + }, +}).sendAndConfirm(umi) ``` -API References: [mintV1](https://mpl-core-candy-machine.typedoc.metaplex.com/functions/mintV1.html), [DefaultGuardSetMintArgs](https://mpl-core-candy-machine.typedoc.metaplex.com/types/DefaultGuardSetMintArgs.html) - {% /dialect %} {% /dialect-switcher %} -## Minting With Pre-Validation +### with pre-validation -It is important to note that some guards may require additional verification steps before we can mint from their Core 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. +For pre-validation, we mean all the guards that may require additional verification steps before the mint like creating an account getting a token that acts as proof of that verification. -### Using the route instruction +This can be done in two ways: -One way guards can require a pre-validation step is by using [their own special instruction](/core-candy-machine/guard-route) 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](/core-candy-machine/guards/allow-list). +- **Using the [route instruction]()**: An example of this is the **[Allowlist Guard](/core-candy-machine/guards/allow-list)** that needs to verify that the wallet belongs to the allowlist providing a valid Merkle Proof. If the route instruction is successful, it will create an Allowlist PDA linked with the wallet wich the Candy Machine instruction will read and validate during the mint. {% diagram %} @@ -479,11 +218,7 @@ A good example of that is the **Allow List** guard. When using this guard, we mu {% /diagram %} -### 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](/core-candy-machine/guards/gatekeeper). +- **Using External Services**: An example of this is the **[Gatekeeper Guard](/core-candy-machine/guards/gatekeeper)** that 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. {% diagram %} @@ -535,16 +270,8 @@ Network, e.g. Captcha. {% /diagram %} -## Minting With Bot Taxes - -One guard you’ll likely want to include in your Core Candy Machine is the Box Tax guard which protects your Core 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 Core Candy Machine account so that, once minting is over, you can access these funds by deleting the Core 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 Core Candy Machine account. [You can learn more about the Bot Tax guard on its dedicated page](/core-candy-machine/guards/bot-tax). - -## Conclusion - -Congratulations, you now know how Core Candy Machines work from A to Z! +## The Bot Tax -Here are some additional reading resources you might be interested in: +The [Bot Tax Guard](/core-candy-machine/guards/bot-tax) protects your Candy Machine against bots by charging mints, that failed because of a Guard, a configurable amount of SOL. All the Sol collected is transferred to the Candy Machine and is accessible by [closing the account](/core-candy-machine/withdrawing-a-candy-machine). -- [All Available Guards](/core-candy-machine/guards): Have a look through all the guards available to you so you can cherry-pick the ones you need. +**Note**: When the Bot Tax Guard gets activated, 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 Core Candy Machine account. diff --git a/src/pages/core-candy-machine/update.md b/src/pages/core-candy-machine/update.md index ea5ca84c..02f463e7 100644 --- a/src/pages/core-candy-machine/update.md +++ b/src/pages/core-candy-machine/update.md @@ -1,5 +1,5 @@ --- -title: Updating The Core Candy Machine +title: Updating a Candy Machine metaTitle: Update a Core Candy Machine | Core Candy Machine description: Learn how to update your Core Candy Machine and it's various settings. --- diff --git a/src/pages/core-candy-machine/withdrawing-a-candy-machine.md b/src/pages/core-candy-machine/withdrawing-a-candy-machine.md index e730a78f..3803561b 100644 --- a/src/pages/core-candy-machine/withdrawing-a-candy-machine.md +++ b/src/pages/core-candy-machine/withdrawing-a-candy-machine.md @@ -12,6 +12,8 @@ Withdrawing a Candy Machine means deleting all its onchain data and retrieving t **Note**: Note: This process applies to all types of Candy Machines (with Config Line Settings, Hidden Settings, and Guards). However, if your Candy Machine has an associated Candy Guard, this instruction will not withdraw the rent from that as well. To learn how to withdraw a Candy Guard, refer to this [paragraph](). +Here is an example of how to withdraw a Core Candy Machine: + {% dialect-switcher title="Withdraw a Core Candy Machine" %} {% dialect title="JavaScript" id="js" %} From 6b8df6651c6d2a345e440088f50a577ffcf9b235 Mon Sep 17 00:00:00 2001 From: L0STE <125566964+L0STE@users.noreply.github.com> Date: Fri, 20 Dec 2024 00:48:44 +0100 Subject: [PATCH 6/6] checkpoint to open the draft PR --- .../products/coreCandyMachine/index.js | 9 +- src/pages/core-candy-machine/guard-groups.md | 271 +++++------------- src/pages/core-candy-machine/guard-route.md | 8 +- 3 files changed, 83 insertions(+), 205 deletions(-) diff --git a/src/components/products/coreCandyMachine/index.js b/src/components/products/coreCandyMachine/index.js index e0b26638..925e6fe6 100644 --- a/src/components/products/coreCandyMachine/index.js +++ b/src/components/products/coreCandyMachine/index.js @@ -27,7 +27,6 @@ export const coreCandyMachine = { { title: 'Getting Started', href: '/core-candy-machine/getting-started', - // Subpages: /js /rust, etc. }, ], }, @@ -67,19 +66,19 @@ export const coreCandyMachine = { links: [ { title: 'Overview', - href: '/core-candy-machine/guards/candy-guard-overview', + href: '/core-candy-machine/guards', }, { title: 'Candy Groups and Phases', - href: '/core-candy-machine/guards/candy-guard-overview', + href: '/core-candy-machine/guard-groups', }, { title: 'Custom Guards', - href: '/core-candy-machine/guards/candy-guard-overview', + href: '/core-candy-machine/guard-route', }, { title: 'Available Candy Guards', - href: '/core-candy-machine/guards/candy-guard-overview', + href: '/core-candy-machine/guards/overview', }, ], }, diff --git a/src/pages/core-candy-machine/guard-groups.md b/src/pages/core-candy-machine/guard-groups.md index cff37c0b..05b72c8d 100644 --- a/src/pages/core-candy-machine/guard-groups.md +++ b/src/pages/core-candy-machine/guard-groups.md @@ -4,41 +4,15 @@ metaTitle: Guard Groups | Core Candy Machine description: Explains how to configure and use multiple groups of guards with a Core Candy Machine. --- -On one of [the previous pages](/core-candy-machine/guards), we introduced guards and used them to define the access control of our Candy Machines. We’ve seen that using guards, we can for instance add payments of 1 SOL per mint and ensure the mint start after a certain date. But what if we also wanted to charge 2 SOL after a second date? What if we wanted to allow certain token holders to mint for free or at a discounted price? {% .lead %} +With Guard Groups, you can define multiple sets of guards, each with its own specific requirements. Thiscreate a fully customizable minting process tailored to your project's needs by introducing: +- **[Phases](#with-phases)**: by setting up different time constraints to each group, +- **[Parallel Groups](#with-parallel-groups)**: by enabling more than one valid group at a given time. -What if we could define multiple sets of guards that each have their own requirements? For that reason, we’ve created **Guard Groups**! +## Create a Candy Guard Group -## How Do Groups Work? +Guard groups work the same way as Candy Guards, but each group is wrapped in a **Label**: a unique text identifier that makes the group unique and can't be longer than 6 character. -Remember [how we can set up guards on any Core Candy Machine](/core-candy-machine/guards#creating-a-candy-machine-with-guards) by simply providing the settings of the guards we want to enable? Well, Guard Groups work the same way, except you must also give them a unique **Label** to identify them. - -Therefore, each Guard Group has the following attributes: - -- **Label**: A unique text identifier. This cannot be longer than 6 characters. -- **Guards**: The settings for all activated guards within that group. This works just like setting up guards directly on the Core Candy Machine. - -Let’s take a quick example. Say we wanted to charge 1 SOL from 4 pm to 5 pm and then 2 SOL from 5 pm until the Core Candy Machine is exhausted. All of that whilst making sure we are protected against bots via the Bot Tax guard. Here’s how we could set up our guards: - -- Group 1: - - **Label**: “early” - - **Guards**: - - Sol Payment: 1 SOL - - Start Date: 4 pm (ignoring the actual date here for the sake of simplicity) - - End Date: 5 pm - - Bot Tax: 0.001 SOL -- Group 2: - - **Label**: “late” - - **Guards**: - - Sol Payment: 2 SOL - - Start Date: 5 pm - - Bot Tax: 0.001 SOL - -And just like that, we’ve created a customized 2-tier minting process! - -Now, whenever someone tries to mint from our Core Candy Machine, **they will have to explicitly tell us which group they are minting from**. Asking for the group label when minting is important because: - -- It ensures buyers do not experience unexpected minting behaviour. Say we tried to mint for 1 SOL at the very end of the first group’s end date but, by the time the transaction executes, we’re now past that date. If we didn’t ask for the group label, the transaction would succeed and we would be charged 2 SOL even though we expected to only be charged 1 SOL. -- It makes it possible to support parallel groups. We’ll talk more about this later on this page. +When minting, users must specify the label of the guard group they want to apply. This is important because multiple groups can be active simultaneously, and, if a user mints near the end of one phase but the transaction processes in the next phase, specifying the label ensures they mint under the intended terms. {% diagram %} @@ -90,56 +64,33 @@ to mint from {% /diagram %} -Now let’s see how we can create and update groups using our SDKs. +### with phases -{% dialect-switcher title="Create a Candy Machine with guard groups" %} -{% dialect title="JavaScript" id="js" %} +As mentioned earlier, Candy Guard Groups allow creating minting phases by assigning different time constraints to each group. -To create Candy Machines with guard groups, simply provide the `groups` array to the `create` function. Each item of this array must contain a `label` and a `guards` object containing the settings of all guards we wish to activate in that group. +For example, to reward early birds, you could charge 1 SOL from 4 PM to 5 PM, then increase the price to 2 SOL from 5 PM until the Core Candy Machine is sold out. Here’s how you could configure the guards for this setup: -Here’s how we’d implement the above example using the Umi library. +- **Group 1 - Label: `early`**: Sol Payment (1 SOL), Start Date (4pm), End Date (5pm) +- **Group 2 - Label: `late`**: Sol Payment (2 SOL), Start Date (5pm) -```ts -import { some, sol, dateTime } from '@metaplex-foundation/umi' +And here's the Code Example for it: -await create(umi, { - // ... - groups: [ - { - label: 'early', - guards: { - solPayment: some({ lamports: sol(1), destination: treasury }), - startDate: some({ date: dateTime('2022-10-18T16:00:00Z') }), - endDate: some({ date: dateTime('2022-10-18T17:00:00Z') }), - botTax: some({ lamports: sol(0.001), lastInstruction: true }), - }, - }, - { - label: 'late', - guards: { - solPayment: some({ lamports: sol(2), destination: treasury }), - startDate: some({ date: dateTime('2022-10-18T17:00:00Z') }), - botTax: some({ lamports: sol(0.001), lastInstruction: true }), - }, - }, - ], -}).sendAndConfirm(umi) -``` - -To update groups, simply provide that same `groups` attribute to the `updateCandyGuard` function. -Please note that the entire `guards` object and `groups` array will be updated meaning **it will override all existing data**! - -Therefore, make sure to provide the settings for all your groups, even if their settings are not changing. You may want to fetch the latest candy guard account data beforehand to avoid overwriting any existing settings. - -Here’s an example, changing the SOL payment guard for the “late” group to 3 SOL instead of 2 SOL. +{% dialect-switcher title="Create a Candy Machine with guard groups" %} +{% dialect title="JavaScript" id="js" %} ```ts -import { some, sol, dateTime } from '@metaplex-foundation/umi' +import { create } from '@metaplex-foundation/mpl-core-candy-machine' +import { some, sol, dateTime, generateSigner } from '@metaplex-foundation/umi' -const candyGuard = await fetchCandyGuard(umi, candyMachine.mintAuthority) -await updateCandyGuard(umi, { - candyGuard: candyGuard.publicKey, - guards: candyGuard.guards, +const candyMachine = generateSigner(); +const collection = publicKey('11111111111111111111111111111111') + +await create(umi, { + candyMachine, + collection, + collectionUpdateAuthority: umi.identity, + itemsAvailable: 1000, + authority: umi.identity.publicKey, groups: [ { label: 'early', @@ -147,115 +98,56 @@ await updateCandyGuard(umi, { solPayment: some({ lamports: sol(1), destination: treasury }), startDate: some({ date: dateTime('2022-10-18T16:00:00Z') }), endDate: some({ date: dateTime('2022-10-18T17:00:00Z') }), - botTax: some({ lamports: sol(0.001), lastInstruction: true }), }, }, { label: 'late', guards: { - solPayment: some({ lamports: sol(3), destination: treasury }), + solPayment: some({ lamports: sol(2), destination: treasury }), startDate: some({ date: dateTime('2022-10-18T17:00:00Z') }), - botTax: some({ lamports: sol(0.001), lastInstruction: true }), }, }, ], }).sendAndConfirm(umi) ``` -API References: [create](https://mpl-core-candy-machine.typedoc.metaplex.com/functions/create.html), [updateCandyGuard](https://mpl-core-candy-machine.typedoc.metaplex.com/functions/updateCandyGuard.html), [DefaultGuardSetArgs](https://mpl-core-candy-machine.typedoc.metaplex.com/types/DefaultGuardSetArgs.html) - {% /dialect %} {% /dialect-switcher %} -## Default Guards - -Notice how, in the example above, we had to provide the same **Bot Tax** guard to both groups. This can be simplified by leveraging the global **Guards** that are set on a Candy Machine. - -When using Guard Groups, the global Guards of a Core Candy Machine — as explained on [a previous page](/core-candy-machine/guards) — **act as default guards**! That means groups will default to using the same guard settings as the global guards unless they are overriding them by explicitly enabling them in the group. - -Here’s a quick recap: - -- If a guard is enabled on the default guards but not on the group’s guards, the group uses the guard **as defined in the default guards**. -- If a guard is enabled on the default guards _and_ on the group’s guards, the group uses the guard **as defined in the group’s guards**. -- If a guard is not enabled on the default guards or the group’s guards, the group does not use this guard. - -To illustrate that, let’s take our example from the previous section and move the **Bot Tax** guard to the default guards. - -- Default Guards: - - Bot Tax: 0.001 SOL -- Group 1: - - **Label**: “early” - - **Guards**: - - Sol Payment: 1 SOL - - Start Date: 4 pm - - End Date: 5 pm -- Group 2: - - **Label**: “late” - - **Guards**: - - Sol Payment: 2 SOL - - Start Date: 5 pm - -As you can see, default guards are useful to avoid repetition within your groups. - -{% diagram %} - -{% node %} -{% node #candy-machine-1 label="Candy Machine" theme="blue" /%} -{% node label="Owner: Candy Machine Core Program" theme="dimmed" /%} -{% /node %} - -{% node parent="candy-machine-1" y=80 x=20 %} -{% node #candy-guard-1 label="Candy Guard" theme="blue" /%} -{% node label="Owner: Candy Guard Program" theme="dimmed" /%} -{% node label="Guards (default guards)" theme="mint" z=1 /%} -{% node label="Bot Tax" /%} -{% node #group-1 theme="mint" z=1 %} -Group 1: "early" {% .font-semibold %} -{% /node %} -{% node label="Sol Payment" /%} -{% node label="Start Date" /%} -{% node label="End Date" /%} -{% node theme="mint" z=1 %} -Group 2: "late" -{% /node %} -{% node label="Sol Payment" /%} -{% node label="Start Date" /%} -{% /node %} +### with default guards -{% node parent="candy-machine-1" x=350 %} -{% node #mint-1 label="Mint" theme="pink" /%} -{% node label="Candy Guard Program" theme="pink" /%} -{% /node %} -{% node parent="mint-1" x=45 y=-20 label="Access Control" theme="transparent" /%} +In the `create` instruction, you can pass both guards and guard groups. The `guards` field acts as default guards applied to all groups unless a specific group overrides them by enabling its own version. -{% node parent="mint-1" x=-22 y=100 %} -{% node #mint-2 label="Mint" theme="pink" /%} -{% node label="Candy Machine Core Program" theme="pink" /%} -{% /node %} -{% node parent="mint-2" x=120 y=-20 label="Mint Logic" theme="transparent" /%} +Here's a quick Recap: +- If a guard is enabled on the default guards but not on the group’s guards: group uses the default guard. +- If a guard is enabled on the default guards _and_ on the group’s guards: group uses group guard. +- If a guard is neither enabled on the default guards nor the group’s guards: group doesn't uses guard. -{% node #nft parent="mint-2" x=62 y=100 label="NFT" /%} +**Note**: even when using default guards, a group must always be provided when minting. That means that is not possible to mint using only the default guards. -{% edge from="candy-guard-1" to="candy-machine-1" fromPosition="left" toPosition="left" arrow=false /%} -{% edge from="mint-1" to="mint-2" theme="pink" path="straight" /%} -{% edge from="mint-2" to="nft" theme="pink" path="straight" /%} -{% edge from="candy-machine-1" to="mint-1" theme="pink" /%} -{% edge from="group-1" to="mint-1" theme="pink" /%} +Here’s how you could configure the guards to include a Bot Tax for both groups: +- **Default Guard**: Bot Tax +- **Group 1 - Label: `early`**: Sol Payment (1 SOL), Start Date (4pm), End Date (5pm) +- **Group 2 - Label: `late`**: Sol Payment (2 SOL), Start Date (5pm) -{% /diagram %} - -Note that, even when using default guards, a group must be provided when minting. That means, when using guard groups, **it is not possible to mint using the default guards only**. +And here's the Code Example for it: {% dialect-switcher title="Create a Candy Machine with default guards and guard groups" %} {% dialect title="JavaScript" id="js" %} -To use default guards in the Umi library, simply use the `guards` attribute in conjunction with the `groups` array when creating or updating a Candy Machine. For instance, here’s how you’d create a Candy Machine using the guard settings described above. - ```ts -import { some, sol, dateTime } from '@metaplex-foundation/umi' +import { create } from '@metaplex-foundation/mpl-core-candy-machine' +import { some, sol, dateTime, generateSigner } from '@metaplex-foundation/umi' + +const candyMachine = generateSigner(); +const collection = publicKey('11111111111111111111111111111111') await create(umi, { - // ... + candyMachine, + collection, + collectionUpdateAuthority: umi.identity, + itemsAvailable: 1000, + authority: umi.identity.publicKey, guards: { botTax: some({ lamports: sol(0.001), lastInstruction: true }), }, @@ -279,73 +171,60 @@ await create(umi, { }).sendAndConfirm(umi) ``` -API References: [create](https://mpl-core-candy-machine.typedoc.metaplex.com/functions/create.html), [DefaultGuardSetArgs](https://mpl-core-candy-machine.typedoc.metaplex.com/types/DefaultGuardSetArgs.html) - {% /dialect %} {% /dialect-switcher %} -## Parallel Groups +### with Parallel Groups -One really interesting benefit of requiring the group label when minting is the ability to have **more than one valid group at a given time**. This removes any ambiguity for the program and allows the buyer to select which group they would like to try to mint from. +As mentioned earlier, Candy Guard Groups allows more than one valid group at a given time by allowing the buyer to select which group they would like to mint from. -Let’s illustrate that with a new example. Say we have an Asset collection called “Innocent Bird” and we want to offer a discounted price of 1 SOL to anyone holding an “Innocent Bird” Asset and charge anyone else 2 SOL. We want both of these groups to be able to start minting at the same time — say 4 pm — and we also want to be protected against bots for both groups. Here’s how we could configure our guards: +For example, you could offer a discount to holders of a specific NFT collection while letting others mint at the regular price: +- **Default Guard**: Bot Tax, Start Date (4pm) +- **Group 1 - Label: `collection`**: Sol Payment (1 SOL), NFT Gate ("Collection Address") +- **Group 2 - Label: `public`**: Sol Payment (2 SOL) -- Default Guards: - - Start Date: 4 pm - - Bot Tax: 0.001 SOL -- Group 1: - - **Label**: “nft” - - **Guards**: - - Sol Payment: 1 SOL - - NFT Gate: “Innocent Bird” Collection -- Group 2: - - **Label**: “public” - - **Guards**: - - Sol Payment: 2 SOL +By selecting the `collection` group, holders of the specified collection will receive a 50% discount on minting. -As you can see, with these guard settings, it is possible for both groups to mint at the same time. It is even possible for an NFT holder to pay the full 2 SOL should they decide to mint from the “public” group. However, it is in their best interest to select the “nft” group if they can. +## Update a Candy Guard Group -{% dialect-switcher title="Create a Core Candy Machine with parallel groups" %} -{% dialect title="JavaScript" id="js" %} +Updating Guards Group work similarly to how you would [update individual Guards](/core-candy-machine/update#updating-the-guards). -Here’s how you’d create a Core Candy Machine using the guard settings described above via the Umi library. +**Note**: Using the `updateCandyGuard()` will update the entire `guards` object and `groups` array overrading all existing data, so be sure to fetch the latest candy guard data beforehand to avoid overwriting any existing settings. + +Here's an example of changing the Sol Payment guards from the `public` group of the [Parallel Groups example](#with-parallel-groups): + +{% dialect-switcher title="Update a Candy Guard Groups" %} +{% dialect title="JavaScript" id="js" %} ```ts import { some, sol, dateTime } from '@metaplex-foundation/umi' -await create(umi, { - // ... - guards: { - botTax: some({ lamports: sol(0.001), lastInstruction: true }), - startDate: some({ date: dateTime('2022-10-18T16:00:00Z') }), - }, +const candyGuard = await fetchCandyGuard(umi, candyMachine.mintAuthority) + +await updateCandyGuard(umi, { + candyGuard: candyGuard.publicKey, + guards: candyGuard.guards, groups: [ { label: 'early', guards: { - solPayment: some({ amount: sol(1), destination: treasury }), - nftGate: some({ - requiredCollection: innocentBirdCollectionNft.publicKey, - }), + solPayment: some({ lamports: sol(1), destination: treasury }), + startDate: some({ date: dateTime('2022-10-18T16:00:00Z') }), + endDate: some({ date: dateTime('2022-10-18T17:00:00Z') }), + botTax: some({ lamports: sol(0.001), lastInstruction: true }), }, }, { label: 'late', guards: { - solPayment: some({ amount: sol(2), destination: treasury }), + solPayment: some({ lamports: sol(3), destination: treasury }), + startDate: some({ date: dateTime('2022-10-18T17:00:00Z') }), + botTax: some({ lamports: sol(0.001), lastInstruction: true }), }, }, ], }).sendAndConfirm(umi) ``` -API References: [create](https://mpl-core-candy-machine.typedoc.metaplex.com/functions/create.html), [DefaultGuardSetArgs](https://mpl-core-candy-machine.typedoc.metaplex.com/types/DefaultGuardSetArgs.html) - {% /dialect %} {% /dialect-switcher %} - -## Conclusion - -Guard groups bring a whole new dimension to our Core Candy Machines by allowing us to define sequential and/or parallel minting workflows tailored to our needs. - -On [the next page](/core-candy-machine/guard-route), we’ll see yet another exciting feature about guards: Guard instructions! diff --git a/src/pages/core-candy-machine/guard-route.md b/src/pages/core-candy-machine/guard-route.md index f4ac7c1c..ea2c0ab2 100644 --- a/src/pages/core-candy-machine/guard-route.md +++ b/src/pages/core-candy-machine/guard-route.md @@ -1,12 +1,12 @@ --- -title: Special Guard Instructions -metaTitle: Special Guard Instructions | Core Candy Machine +title: Custom Guard Instructions +metaTitle: Custom Guard Instructions | Core Candy Machine description: Explains how to execute guard-specific instructions for the Core Candy Machine. --- -As we’ve seen on the previous pages, guards are a powerful way to customize the minting process of your Candy Machines. But did you know guards can even provide their own custom instructions? {% .lead %} +Guards offer a powerful way to customize your Candy Machine minting process, but the `Route Guard` offer the more advanced creator an even more customizable exprience allowing for custom behaviour. -## The Route Instruction +## The Route Guard The Core Candy Guard program ships with a special instruction called **the “Route” instruction**.