# How to: Candy Machine v2 Whitelist
###### tags: `metaplex` `whitelist`
A comprehensive, step-by-step tutorial, for you to launch your NFT project with whitelist using Candy Machine V2, SPL Tokens, and Gumdrop.
```sequence
Developer->SPL: 1. Create/mint token
Developer->CandyMachine: 2. Create/upload assets + wl settings
Developer->Gumdrop: 3. Create & set the whitelist
Gumdrop->User: Distribution
User->ClaimSite: Claim tokens
ClaimSite-->User: tokens
User->MintSite: Initiate the Mint
User->CandyMachine: Mint NFT using token
CandyMachine-->User: NFT
```
:::info
:information_source: You should always read the [official docs](https://docs.metaplex.com/) and keep up with the community updates.
:::
### Environment Setup
Install the required tools as described in the [official guide](https://docs.metaplex.com/candy-machine-v2/getting-started).
:::spoiler _Versions & Downloads_
You'll need all of these installed (don't need to be exact versions):
```bash
$ git version
git version 2.34.1
$ node --version
v16.13.1
$ yarn --version
1.22.17
$ ts-node --version
v10.4.0
$ solana --version
solana-cli 1.8.11 (src:423a4d65; feat:2385070269)
```
Download links:
- Git - https://git-scm.com/downloads
- Node.js - https://nodejs.org/en/download/
- Yarn - https://classic.yarnpkg.com/lang/en/docs/install
_(Use `yarn v1.x` - later versions need extra config)_
- ts-node - https://www.npmjs.com/package/ts-node#Installation
- Solana Tool Suite - https://docs.solana.com/cli/install-solana-cli-tools
Only need Solana CLI? Run this bad boy:
```bash
sh -c "$(curl -sSfL https://release.solana.com/stable/install)"
```
I'm running on `WSL2` Ubuntu:
```
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 20.04.3 LTS
Release: 20.04
Codename: focal
```
:::
### Environment Variables
Setup the variables we'll need for this example:
```bash
# Environment
export ENV='devnet'
export URL='https://api.devnet.solana.com'
export KEYPAIR="$HOME/.config/solana/devnet.json"
export RPC='https://api.devnet.solana.com'
# Candy Machine
export EXTRAS='./extras'
export CONFIG="$EXTRAS/config.json"
export WHITELIST="$EXTRAS/whitelist.json"
# Collection
export ASSETS="$EXTRAS/assets"
```
:::spoiler _Setup your free custom RPC provider (Optional for this tutorial)_
This tutorial uses an RPC provider on all commands. Create a free one on Figment:
1. Sign up to Figment here: https://datahub.figment.io/sign_up?service=solana
3. Find and copy your `API Key` and the base URL.
3. Set this URL as your RPC variable:
```bash
export RPC='https://solana--devnet.datahub.figment.io/apikey/<YOUR API KEY>'
```
:::
### Create your Treasury Wallet
Create and fund your wallet:
```bash
solana config set --url $URL
solana config set --keypair $KEYPAIR
solana-keygen new --outfile $KEYPAIR
solana airdrop 2 --keypair $KEYPAIR
```
:bulb: Copy the public key - you'll need it later.
You can always get the public key later:
```bash
solana-keygen pubkey
```
### Create the SPL Token
Whitelisted users will be allowed to mint using SPL Tokens which will serve as an exchange currency. Create the token:
```bash
spl-token create-token --decimals 0
```
:bulb: Copy the token - you'll need it later.
Store the output value and set the token address variable like this:
```sh
export SPL_TOKEN="<YOUR NEW TOKEN JUST CREATED>"
```
Mint the tokens:
```bash
spl-token create-account $SPL_TOKEN
spl-token mint $SPL_TOKEN 10
# Consider disabling the mint when you're done
spl-token authorize $SPL_TOKEN mint --disable
```
For `mainnet` you should [register the token](https://github.com/solana-labs/token-list).
### Candy Machine Configuration
Get the Metaplex code, then install the dependencies:
```bash
git clone 'git@github.com:metaplex-foundation/metaplex.git'
cd metaplex
yarn install --cwd ./js/
```
Create the `extras` directory and the `config.json`:
```bash
mkdir extras
touch ./extras/config.json
```
Copy/paste the following JSON content into `config.json`:
```json
{
"price": 0.5,
"number": 10,
"gatekeeper": null,
"solTreasuryAccount": "<YOUR WALLET ADDRESS>",
"splTokenAccount": null,
"splToken": null,
"goLiveDate": "30 Jan 2022 00:00:00 UTC",
"endSettings": null,
"whitelistMintSettings": {
"mode": {
"burnEveryTime": true
},
"mint": "<SPL TOKEN>",
"presale": true,
"discountPrice": 0.33
},
"hiddenSettings": null,
"storage": "arweave",
"ipfsInfuraProjectId": null,
"ipfsInfuraSecret": null,
"awsS3Bucket": null,
"noRetainAuthority": false,
"noMutable": false
}
```
:arrow_forward: Update `config.json` with your custom configuration:
- **`solTreasuryAccount`** - The public key of the keypair of the Treasury Account.
- **`goLiveDate`** - Set a date in the future to allow for the whitelist behavior.
- **`whitelistMintSettings.mint`** - This is the SPL Token created earlier.
Notice that the `discountPrice` is 0.33. It will override the `price` 0.5 only for the whitelist.
Check out the [official docs](https://docs.metaplex.com/candy-machine-v2/configuration) to learn more about these configurations.
### Prepare the Assets
Download the sample assets:
```bash
wget -O 'assets.tar.gz' https://github.com/epomatti/cmv2-whitelist/blob/main/assets.tar.gz?raw=true
tar -xzf assets.tar.gz --directory $EXTRAS
```
:arrow_forward: Update all JSON files under `./extras/assets`
For this example, change **`properties.creators.address`** value to your Treasury Account public key.
### Create the Candy Machine :candy:
This command will create the candy machine and upload all assets.
```bash
ts-node ./js/packages/cli/src/candy-machine-v2-cli.ts upload \
--env $ENV \
--keypair $KEYPAIR \
--config-path $CONFIG \
--rpc-url $RPC \
$ASSETS
```
:bulb: Wait for all assets to be uploaded, then copy the candy machine ID - you'll need it later
For more info on the metadata check the [official docs](https://docs.metaplex.com/nft-standard).
:::info
:information_source: The `number` of NFTs cannot be changed later, so make sure to get it right on `mainnet`
:::
Verify the uploads:
```bash
ts-node ./js/packages/cli/src/candy-machine-v2-cli.ts verify_upload \
--env $ENV \
--keypair $KEYPAIR \
--rpc-url $RPC
```
You need an output like this before going forward:
```
Key size 10
uploaded (10) out of (10)
ready to deploy!
```
:::spoiler _Click here if you need to Upload the candy machine_
```bash
# If you make changes in the "config.json"
ts-node ./js/packages/cli/src/candy-machine-v2-cli.ts update_candy_machine \
--env $ENV \
--keypair $KEYPAIR \
--config-path $CONFIG \
--rpc-url $RPC
```
:::
### Create the Gumdrop
On this tutorial we're using `gumdrop` but you may use other means for token distribution.
Create the `whitelist.json` file which will hold the list of whitelisted users:
```bash
touch ./extras/whitelist.json
```
Copy and paste the following content into the `whitelist.json`:
```json
[
{
"handle": "<USER WALLET>",
"amount": 1
}
]
```
:arrow_forward: Now change the `handle` property value to the user wallet.
The `handle` here is the public wallet address of the user that will be whitelisted. You can create a new one in your Phantom wallet connected to the `devnet` network.
:arrow_forward: Add funds to the new user wallets: https://solfaucet.com/
:::spoiler _Demo: Create a Phantom user wallet on `devnet`_
![](https://i.imgur.com/aauLh6q.gif)
:::
<br/>
:::info
:information_source: Read the [official docs](https://docs.metaplex.com/airdrops/create-gumdrop) to learn more about other distribution methods (email, SMS, ...)
:::
Here we'll use the [Token Airdrop](https://docs.metaplex.com/airdrops/create-gumdrop#token-airdrop) drop type supported by `CMv2`.
Create the `gumdrop`:
```bash
ts-node ./js/packages/cli/src/gumdrop-cli.ts create \
--env $ENV \
--keypair $KEYPAIR \
--rpc-url $RPC \
--claim-integration "transfer" \
--transfer-mint $SPL_TOKEN \
--distribution-method "wallets" \
--otp-auth "disable" \
--distribution-list $WHITELIST
```
:bulb: Copy the `gumdrop` ID - you'll need it later.
:::info
:information_source: Real launches should consider a custom `--host` deployment. Check the gumdrop docs.
:::
### URL Claim the SPL Token
Under the **`./logs`** folder the URLs have been generated in the `devnet-urls.json` file.
![](https://i.imgur.com/yJnIetz.png)
:arrow_forward: Open the URL and claim your token
Users will claim their own tokens using this URL and use their tokens as proof for whitelist privileges while minting their NFTs.
:::spoiler _Demo: Claiming the token with a user wallet_
![](https://i.imgur.com/xBOAYlr.gif)
:::
### Setup the Minting Frontend
:::success
:rocket: Updated to use the newly released [Candy Machine UI](https://docs.metaplex.com/candy-machine-v2/mint-frontend) module.
:::
The frontend is available at `./js/packages/candy-machine-ui`.
```bash
export CANDYUI='./js/packages/candy-machine-ui'
cp "$CANDYUI/.env.example" "$CANDYUI/.env"
```
:arrow_forward: Edit the `.env` file with your own configuration:
```
REACT_APP_CANDY_MACHINE_ID=<YOUR CANDY MACHINE PROGRAM ID>
REACT_APP_SOLANA_NETWORK=devnet
REACT_APP_SOLANA_RPC_HOST=https://api.devnet.solana.com
```
If you're using a custom RPC server, change that too.
Now install & start your minting frontend:
```bash
yarn --cwd $CANDYUI install
yarn --cwd $CANDYUI start
```
:::spoiler _Click here if you forgot your Candy Machine ID_
Run this to see your Candy Machine configuration:
```bash
ts-node ./js/packages/cli/src/candy-machine-v2-cli.ts show \
--env $ENV \
--keypair $KEYPAIR \
--rpc-url $RPC
```
Copy the ID:
![](https://i.imgur.com/s5KW4UC.png)
:::
### Mint an NFT providing your SPL Token
Whitelisted users will then connect to the minting site and mint the NFT.
They will exchange the token as part of the whitelist + the SOL price configured in the `config.json` discount property.
:arrow_forward: Site should be running here: **http://localhost:3000**
![](https://i.imgur.com/ugMU789.gif)
As expected, the whitelist price is 0.33 SOL and the SPL Token is removed from the user wallet.
:::info
:information_source: Opened [this issue](https://github.com/metaplex-foundation/metaplex/issues/1465) to fix the displayed price, as it should be aware of the discount.
:::
### Close the Gumdrop
Finally, once the whitelist launch is over, you should close the `gumdrop`:
```sh
ts-node ./js/packages/cli/src/gumdrop-cli.ts close \
--env $ENV \
--keypair $KEYPAIR \
--rpc-url $RPC \
--claim-integration "transfer" \
--transfer-mint $SPL_TOKEN \
--base '.log/devnet-XXXXXXXXXXXXX.json'
```
Check the [official docs](https://docs.metaplex.com/airdrops/create-gumdrop#closing-a-gumdrop) for this closing behavior.
---
I hope you find this article useful.
Let me know of any fixes in the comments, or reach out on Twitter: [@EvandroPomatti](https://twitter.com/EvandroPomatti)