15 min read
This guide uses Sugar V2 with Candy Machine V3, which has been deprecated. For new NFT projects, see How to Launch an NFT Collection with Metaplex Core Candy Machine. This guide is for historic educational purposes only.
概覽
Are you ready to launch your NFT collection on Solana? Metaplex's Candy Machine CLI, Sugar, is the tool for you to launch in no time. If you have used previous versions of Candy Machine, you will notice that Sugar has a few significant improvements:
- 提升上傳效能
- 簡化版使用者體驗
- 改進錯誤處理機制
您將負責的工作內容
In this guide, you will create a new wallet using Solana CLI, airdrop some SOL, and deploy a Candy Machine on Solana's devnet using Sugar. You'll then deploy your Candy Machine to the web using the Solana dApp Scaffold and Metaplex's new modular JS framework, Umi.
您需要準備的物品
- Node.js installed (version 16.15 or higher)
- 已安裝Solana CLI
- 已安裝Phantom Wallet或Solflare 擴充功能
- Metaplex Sugar installed (**Latest Version, V2.x+ **) (installation instructions below)
- 文字編輯器
- npm or yarn installed (We will use yarn to initialize our project and install the necessary packages. Feel free to use npm instead if that's your preferred package manager.)
設定您的專案
Create a new project directory in your terminal with the following:
mkdir sugar-demo
cd sugar-demo
安裝 Sugar
During installation, you will be asked which version you want to use. V1.x is for Candy Machine v2, V2.x is for Candy Machine v3. This guide assumes you are using V2.x. (Candy Machine v3). If you are using an older version, check out our guide here.
Mac 安裝
In your terminal, enter:
bash <(curl -sSf https://sugar.metaplex.com/install.sh)
注意:安裝完成後,您可能需要重新啟動終端機
Windows 安裝
- Download the Windows installer here.
- 以系統管理員身分執行安裝程式(右鍵點擊-->以系統管理員身分執行). If you get a warning about an untrusted binary, try clicking 更多資訊 然後 《不管怎樣,還是跑吧》. 若您沒有此選項,請依照以下步驟操作:
- 在可執行檔案上按右鍵,然後選擇「內容」。
- If you trust the Metaplex developer team, check the Unblock button as shown in the image below. This will allow you to run this binary on your computer since Microsoft does not trust it automatically.
- 按下「套用」和「確定」。
- 請再次執行安裝程式
如果一切運作正常,您應該會看到類似以下的內容:

You should be able to verify your sugar installation by entering sugar --version in your terminal. You should see something like this:
Quicknode % sugar --version
sugar-cli 2.5.0
建立新錢包
One of the cool new features of Sugar is that it will allow you to set your wallet and RPC configs using Solana CLI so that you don't need to re-enter them in each of your Sugar commands.
我們首先需要使用以下指令,建立一個專門用於 devnet 測試的新錢包:
solana-keygen new --no-bip39-passphrase --outfile ./wallet.json
We can confirm that the wallet we just generated is the wallet that the Solana CLI will use by running the following:
Solana 設定 設定 --keypair ./wallet.json
Note: we are using a relative path to our wallet in this example as we will not be changing directories, but you may include a full path if you prefer.
建立與您的 Quicknode RPC 的連線
使用您的 Quicknode 端點連線至 Solana 叢集
若要在 Solana 上進行開發,您需要一個 API 端點來連線至該網路。您可以使用公開節點,或自行部署並管理基礎架構;不過,若您希望將回應時間縮短 8 倍,不妨將繁重的工作交給我們處理。
了解為何在 索拉納 選擇 Quicknode,立即開始免費試用 這裡. 我們將使用一個 索拉納 Devnet 終點。
複製該 HTTP 服務提供者連結:
在 Solana Devnet 上設定好您的終端點後,現在您可以執行此指令,並將 YOUR_QUICKNODE_URL 使用您已複製的 HTTP URL:
Solana 設定 設定 --url 您的 QuickNode URL
Now to fund your wallet, you can run the command:
Solana 空投 1
If the command is successful, you should see something like this:

您也可以執行 Solana 餘額 在您的終端機中查看,確認那 1 SOL 確實存在。
準備 NFT 資產
If you have used Candy Machine before, this process will be familiar. We must create a .json file corresponding to each digital asset using a simple number format starting with 0 and increasing sequentially, never skipping a number (e.g., 0.json maps to 0.png, then 1.json maps to 1.png). We can also create an optional collection.json and collection.png to enable Sugar to create an on-chain collection automatically.
Metaplex 提供了一組範例資產,我們可以下載並加以運用,以確保一致性。您可以編輯該 JSON 檔案,加入您想要的任何值,只要符合URI JSON 模式即可。
Download the sample set and extract the contents to ./assets/ in your project directory (the default directory that Sugar will look for your files).
設定糖果機
Create a new file, config.json, in your root project folder:
echo > config.json
開啟該檔案,並將此設定貼入其中:
{
"number": 10,
"symbol": "NB",
"sellerFeeBasisPoints": 500,
"isMutable": true,
"isSequential": false,
"ruleSet": null,
"creators": [
{
"address": "YOUR_WALLET_ADDRESS",
"share": 100
}
],
"uploadMethod": "bundlr",
"awsS3Bucket": null,
"retainAuthority": true,
"awsConfig": null,
"nftStorageAuthToken": null,
"shdwStorageAccount": null,
"pinataConfig": null,
"hiddenSettings": null,
"guards": {
"default": {
"solPayment": {
"value": 0.01,
"destination": "YOUR_WALLET_ADDRESS"
},
"startDate": {
"date": "2022-10-23T20:00:00Z"
}
}
}
}
Make sure to replace YOUR_WALLET_ADDRESS with the wallet address you created earlier.
注意:您可以在終端機中執行「solana address」指令,以取得您剛建立的錢包地址。
Now, we should be all set. If you're following along to this point, you should have a directory structure like this:
sugar-demo/
├── wallet.json
├── config.json
└── assets/
├── [0-9].png
├── [0-9].json
├── collection.png
└── collection.json
Sugar has a built-in validation tool that will let us check for errors before proceeding. In the terminal, run:
sugar 驗證

Note: You may see a warning, "missing properties.category". This is fine as the attribute is not included in the Metaplex sample files.
我們開始了!做得好。來組裝我們的糖果機吧。
Create a Candy Machine
Because we have set our RPC and wallet using Solana CLI and saved our assets 以及 config.json to Sugar's default directories, our commands will be pretty simple!
上傳您的素材
In your terminal, enter:
sugar 上傳
您應該會看到類似以下的內容:

部署糖果機
In your terminal, enter:
sugar deploy
您應該會看到類似以下的內容:

If you get a "Blockhash not found" error, try rerunning the command.
Make sure to store the Candy Machine ID provided in your terminal locally. We will need this later.
驗證糖果機
Let's make sure everything has worked as we'd expected. In your terminal, enter:
sugar 驗證
您應該會看到類似以下的內容:

做得真棒!
測試您的糖果機
Try minting an NFT using sugar. In your terminal, enter:
糖薄荷
您應該會看到類似以下的內容:

Add Your Candy Guards
By default, when you deploy your Candy Machine, only you can mint NFTs. You must implement candy guards to define the criteria by which others can mint your NFTs (e.g., start time, payment amount, payment token, whitelist tokens, etc.). Since we already defined our guards in our config.json, we can run the following:
sugar guard add

Excellent! Let's create a mint page to share this project with the world!
建立一個鑄幣網站
For a speedy deployment, we will be using the Solana dApp Scaffold, a handy tool that includes a Next.JS app with Solana Wallet Adapter already integrated.
Clone the dApp Scaffold
From your project directory, in your terminal, enter:
git clone https://github.com/solana-labs/dapp-scaffold ./candy-machine-ui/
cd candy-machine-ui
Install Dependencies
Install the included dependencies. In your terminal, enter:
紗線
We will need a few additional metaplex packages to get our minting site up and running. In your terminal, enter:
yarn add @metaplex-foundation/mpl-candy-machine@alpha @metaplex-foundation/mpl-token-metadata@alpha @metaplex-foundation/mpl-toolbox @metaplex-foundation/umi @metaplex-foundation/umi-bundle-defaults @metaplex-foundation/umi-signer-wallet-adapters
Create a .env File
Create a file, .env in the candy-machine-ui folder:
echo > .env
Add the following values in the new .env file (replacing the values with your own):
NEXT_PUBLIC_RPC=<YOUR_QUICKNODE_URL>
NEXT_PUBLIC_CANDY_MACHINE_ID=<YOUR_CANDY_MACHINE_PUBKEY>
NEXT_PUBLIC_TREASURY=<YOUR_WALLET_ADDRESS>
If you don't remember your Candy Machine ID, you should be able to find it in cache.json in the program.candyMachine field.
With all that information plugged in, you can save the file.
Add Mint NFT Button
We must add a button to our minting site to allow users to mint an NFT. First, duplicate the RequestAirdrop component and rename it to CandyMint. In your terminal, copy the file by entering the following:
cp ./src/components/RequestAirdrop.tsx ./src/components/CandyMint.tsx
開啟 CandyMint.tsx and change the exported component name from RequestAirdrop 至 CandyMint. You should also change the text in the button from <span>Airdrop 1 </span> 至 <span>Mint NFT </span>.
Finally, let's update our constant declarations and clear the contents of the onClick function, so we have a clean slate to work with. Your file should look like this:
//...Default Imports (we will replace these later)
export const CandyMint: FC = () => {
// 👇 Update these constant declarations
const { connection } = useConnection();
const wallet = useWallet();
const { getUserSOLBalance } = useUserSOLBalanceStore();
// TODO - Create an Umi instance
// 👇 Update this onClick function
const onClick = useCallback(async () => {
if (!publicKey) {
console.log('error', 'Wallet not connected!');
notify({ type: 'error', message: 'error', description: 'Wallet not connected!' });
return;
}
// TODO - Add minting logic here
}, []);
return (
<div className="flex flex-row justify-center">
<div className="relative group items-center">
<div className="m-1 absolute -inset-0.5 bg-gradient-to-r from-indigo-500 to-fuchsia-500
rounded-lg blur opacity-20 group-hover:opacity-100 transition duration-1000 group-hover:duration-200 animate-tilt"></div>
<button
className="px-8 m-2 btn animate-pulse bg-gradient-to-br from-indigo-500 to-fuchsia-500 hover:from-white hover:to-purple-300 text-black"
onClick={onClick}
>
<span>Mint NFT </span>
</button>
</div>
</div>
);
};
We need to add the CandyMint component to our Home View. Open ./sugar-demo/candy-machine-ui/src/views/home/index.tsx and add the following import statement:
// Components
import { RequestAirdrop } from '../../components/RequestAirdrop';
// 👇 Add this line
import { CandyMint } from '../../components/CandyMint';
And add the CandyMint component to the HomeView component:
<RequestAirdrop />
{/* 👇 Add this line */}
<CandyMint />
Great job! You should now have a new button, but before we test it, we need to add mint functionality. Let's do that.
Add Mint Functionality
Return to ./sugar-demo/candy-machine-ui/src/components/CandyMint.tsx and replace the default imports with the following:
import { useConnection, useWallet } from '@solana/wallet-adapter-react';
import { FC, useCallback, useMemo } from 'react';
import { notify } from "../utils/notifications";
import useUserSOLBalanceStore from '../stores/useUserSOLBalanceStore';
import { createUmi } from '@metaplex-foundation/umi-bundle-defaults';
import { generateSigner, transactionBuilder, publicKey, some } from '@metaplex-foundation/umi';
import { fetchCandyMachine, mintV2, mplCandyMachine, safeFetchCandyGuard } from "@metaplex-foundation/mpl-candy-machine";
import { walletAdapterIdentity } from '@metaplex-foundation/umi-signer-wallet-adapters';
import { mplTokenMetadata } from '@metaplex-foundation/mpl-token-metadata';
import { setComputeUnitLimit } from '@metaplex-foundation/mpl-toolbox';
import { clusterApiUrl } from '@solana/web3.js';
import * as bs58 from 'bs58';
// These access the environment variables we defined in the .env file
const quicknodeEndpoint = process.env.NEXT_PUBLIC_RPC || clusterApiUrl('devnet');
const candyMachineAddress = publicKey(process.env.NEXT_PUBLIC_CANDY_MACHINE_ID);
const treasury = publicKey(process.env.NEXT_PUBLIC_TREASURY);
Create a Umi Instance
Let's create a memoized Umi instance using our Quicknode Endpoint and the mplCandyMachine and mplTokenMetadata plugins. We will use this to mint our NFTs. Replace // TODO - Create Umi instance with:
const umi = useMemo(() =>
createUmi(quicknodeEndpoint)
.use(walletAdapterIdentity(wallet))
.use(mplCandyMachine())
.use(mplTokenMetadata()),
[wallet, mplCandyMachine, walletAdapterIdentity, mplTokenMetadata, quicknodeEndpoint, createUmi]
);
This will create a Umi instance that uses our wallet connected via the wallet adapter, our Quicknode endpoint, and a couple of Metaplex plugins.
Add Minting Logic
Let's update our onClick function to mint an NFT using Umi's transaction builder. Replace the onClick function with the following code, and then we will walk through what is happening:
const onClick = useCallback(async () => {
if (!wallet.publicKey) {
console.log('error', 'Wallet not connected!');
notify({ type: 'error', message: 'error', description: 'Wallet not connected!' });
return;
}
// Fetch the Candy Machine.
const candyMachine = await fetchCandyMachine(
umi,
candyMachineAddress,
);
// Fetch the Candy Guard.
const candyGuard = await safeFetchCandyGuard(
umi,
candyMachine.mintAuthority,
);
try {
// Mint from the Candy Machine.
const nftMint = generateSigner(umi);
const transaction = await transactionBuilder()
.add(setComputeUnitLimit(umi, { units: 800_000 }))
.add(
mintV2(umi, {
candyMachine: candyMachine.publicKey,
candyGuard: candyGuard?.publicKey,
nftMint,
collectionMint: candyMachine.collectionMint,
collectionUpdateAuthority: candyMachine.authority,
mintArgs: {
solPayment: some({ destination: treasury }),
},
})
);
const { signature } = await transaction.sendAndConfirm(umi, {
confirm: { commitment: "confirmed" },
});
const txid = bs58.encode(signature);
console.log('success', `Mint successful! ${txid}`)
notify({ type: 'success', message: 'Mint successful!', txid });
getUserSOLBalance(wallet.publicKey, connection);
} catch (error: any) {
notify({ type: 'error', message: `Error minting!`, description: error?.message });
console.log('error', `Mint failed! ${error?.message}`);
}
}, [wallet, connection, getUserSOLBalance, umi, candyMachineAddress, treasury]);
Let's walk through what is happening here:
- First, we check to make sure the wallet is connected. If it is not, we notify the user and return.
- Next, we fetch the Candy Machine and Candy Guard using the
fetchCandyMachine以及safeFetchCandyGuardfunctions from the mpl-candy-machine package. We need these for our minting transaction. - Next, we generate a signer using Umi's
generateSignerfunction. This will be used to mint our NFT. - Next, we create a transaction using Umi's
transactionBuilderfunction. This will be used to mint our NFT:
- We add a
setComputeUnitLimitinstruction to the transaction. This safety measure prevents the transaction from failing due to exceeding the compute unit limit. - We add a
mintV2instruction to the transaction. This is the instruction that will mint our NFT. We pass our umi instance and an object with the following properties:candyMachine: The candy machine's public key.candyGuard: The candy guard's public key.nftMint: The signer we generated earlier.collectionMint: The collection mint's public key.collectionUpdateAuthority: The collection update authority's public key.mintArgs: An object containing the mint arguments associated with your Candy Guard (this may be different depending on your Candy Guard). For thesolPaymentguard, we must pass thedestinationof the payment (the treasury's public key).
- We send the transaction and notify the user of the result. Note that umi returns transaction signatures as a Unit8Array, so we must encode it to base58 before displaying it to the user.
- Finally, we call
getUserSOLBalance(a store action built into the scaffold) to update the user's SOL balance.
Nice job! Our site should now be able to mint NFTs.
Mint an NFT
Now that we have added the minting logic, let's start and test the site. In your terminal, run the following:
yarn dev
這將開啟瀏覽器並連至localhost:3000,您可以在該處連接您的錢包並鑄造 NFT。在繼續之前,請確認您的 Phantom 錢包已設定為開發網(devnet),而非主網(mainnet)。
若要鑄造 NFT,您的 Phantom 錢包中必須有 devnet SOL。您可以使用 Solana CLI 將 SOL 空投至您的 Phantom 錢包,方法是在終端機中輸入以下指令:
Solana 空投 1 您的 Phantom 錢包地址
準備就緒後,請點擊「Mint」。若操作成功,您應會看到類似以下的網站:

If you see an error that says “Mint Failed,” you might not have enough funds. Try again once you have added funds. You can view the NFT in your wallet after purchasing. Phantom may take a moment before rendering the NFT in your wallet. Ours looks like this:

這糖真甜啊!做得真棒。
結論
Congrats! You created a Candy Machine using Metaplex Sugar and Umi. You now have all the tools needed to run your own NFT mint. We're excited to see what NFTs you're creating! Join us on Discord or reach out to us via Twitter to share your NFT project.
我們 ❤️ 您的回饋!
如果您有任何意見回饋或對新主題的建議,請告訴我們。我們非常樂意聽取您的意見。
