Generative NFTs are one of booming trends in the crypto space. Artists or people who are passionate about this new trend are creating their generative NFT collections. A collection of Generative NFTs is a set of NFTs created by an algorithms. Each NFT in the collection is a combination of different Components. Creator designs and provides these components for the algorithm.
In this tutorial, you will learn to create a collection of generative NFTs and a minting machine on the Solana blockchain.
First, you'll generate your NFT collection using an algorithm and then you'll upload those to arweave using metaplex and finally, you'll create a marketplace for users to mint your NFTs. You can refer to pixelape.art as an example of the final result.
- A GitHub account
- A code editor, VS Code is recommended
- You will need git installed
- You will need Solana CLI installed
- You will need NodeJS(v14.18.1+) installed
- You will need ts-node installed
- You will need Yarn installed
- You will need Phantom extension installed
To successfully launch your Collection on Solana you'll need to go through three steps:
- Generating your collection of unique NFTs using the hashlips art engine
- Uploading the collection to Arweave using metaplex
- Creating a store for the collection using a Metaplex "candy machine"
We will go into more detail regarding the tools later in the tutorial. First, you need to create an empty folder on your desktop to contain the project files. Then clone these repositories into that project folder (links are also provided in the References section at the end of the tutorial).
For that open a terminal in your desktop. Then run command below to create a folder:
And navigate the current working directory to that folder by running
Now to clone repositories run commands below respectively:
To ensure you have the Solana CLI installed, run the command
solana --versionin a terminal. If it shows the version, then the Solana CLI is installed. Otherwise, you need to use the install tool provided by Solana.
To see the current configuration details being used by the Solana CLI, you can always run the command
solana config getin a terminal:
To change the default network to devnet, use
solana config set --url devnet:
Then create a wallet by running the command below:
Terminal prompts message below:
You can enter a password but make sure you save your entered passphrase in a safe place because if you forget it you wouldn't be able to restore your wallet.
Then set this new wallet as the default wallet in the Solana CLI:
And finally, airdrop some SOL to your new wallet:
solana airdrop 5
And to check whether it was successful:
Later in the tutorial, you will connect Phantom to your NFT minting dApp to mint some NFTs. Let's add the wallet you just created for devnet to Phantom. We can view the path to our wallet by running
solana config get:
Copy the Keypair Path shown in your terminal: "/home/<your username>/.config/solana/devnet.json"
Next, run the following command to print the contents of the
devnet.jsonfile in your terminal - This will be an array:
Now you need to open the Phantom wallet extension in your browser. From the hamburger menu on the left, click "Add / Connect Wallet":
Then choose a name and copy-paste the private key:
Since you will be working with devnet, you need to set the network to devnet in the Phantom wallet settings. For that click on the gear icon, then "Change Network" then "Devnet":
Each NFT in a generative NFT collection is a combination of different layers. Each layer defines a part of the NFT. for example if our collection is about the human face, layers could be:
- Hair style
- Hair color
- Eye color
- Eye size
For each layer, the creator of the collection can design different variants. For example for background, the creator can provide different colors as background.
When creating NFT collections, large in size like 10,000 NFTs, it is not efficient to expect the creator of the collection to create all of these unique NFTs as they do in small collections.
This is where we need an algorithm which uses the provided layers and creates unique NFT assets. Hash lips art engine is an open-source engine built for this purpose. If we provide unique classified layers for our collection, NFTs are guaranteed to be unique by the engine.
In this tutorial, we will create a very simple set of layers to give you an idea about them. you may want to spend more time on this step and provide much more details in your layers.
You can use any tool like photoshop or something similar for creating your layers but make sure the layers which are going to sit on top of other layers have a transparent background. Here are some simple layers I created using the paint app!
So now I have 3 layers and overall 8 traits. You can download these layers from the link in the References section at the end of the tutorial.
In the hashlips engine, we can specify the rarity of a trait within a group of traits. To do that we add a
#and a percentage to the end of the assets' file name. For example, if we wanted background2.png to appear 80% of the time we would rename it to
background2#80.png. For the other background, it will appear 20% of the time (80 + 20 = 100) so we would rename it
So for each layer (background, triangle, or circle), we specify the rarity of traits. The sum of rarity percentages should always equal 100. Here is an example:
The next step is putting our layers in the layers folder. Navigate to the layers directory inside of the hashlips submodule that we cloned at the beginning of the tutorial, and then remove the existing folders and their contents:
When this is done, create three new folders named for the layers we will be using: Background, Circle and Triangle (make sure the first letter is Uppercase!). Next, copy the images into their respective directories and rename the files to include the rarity percentages if you have not already done so.
We need to set up metadata related to our collection like the owner of the collection or the name of the collection. To do that we need to open the
hashlips_art_engine/src/config.jsfile. Let's go through the code inside this file step by step and configure our NFT collection.
This part of the code imports some internal variables and modules and you don't need to touch it.
network: To deploy to Solana, we must change the target network from eth to sol:
Here you can specify the name and a description for your collection - ignore the comment that it is for Ethereum. You can also ignore the baseUri.
Here we set up metadata specific to Solana NFTs.
symbol: In symbol, you can set an abbreviation for the name of your collection. I chose the first letters of the words in the name.
seller_fee_basis_points: This parameter specifies the share which creators want to earn from future sales of their NFTs. Each point is 0.01% so if a creator wants to earn 1% from future trades of their collection they should set it to 100 points. This parameter is also referred to as a royalty percentage.
external_url: If the collection has a website or a YouTube channel or a link related, you can put it here.
creators: In this field, you can specify shares of profit between creators. If there is just a single creator then you can put the public key of them in the address field and set the share field to 100 (standing for 100%).
If there is more than one creator for the collection, you can add a similar object in the creators array for all other creators and set their shares and their Solana addresses. For this collection, we are the only creator so set the shares to 100 and put our Solana address for address.
growEditionSizeTo: In this part of the code we specify the number of NFTs we want to generate. An important factor to consider here is the maximum unique NFTs we can expect to yield from the layers we have provided. We have 3 circles, 3 triangles and 2 backgrounds so the maximum number of unique NFTs is 3 x 3 x 2 = 18. You can put any number equal to or less than the maximum possible number of unique NFTs given how many layers you are using. For this tutorial, a number between 1-18 will work.
layersOrder: In this field, we specify the order we want the layers to sit on each other. Since the background is the bottom-most layer we put it first and the other two layers after that.
We are done with configuring our collection but for the advanced configuration, you can follow the next chapter.
shuffleLayersConfigurations: This field is for when we have more than one layer configuration. It can be true or false. Here is an example:
In the example above we have two configurations. If we set the shuffleLayersConfigurations field to true the engine wouldn’t follow the order of our configurations. For example image number 1 can be created from any of these configurations. Shuffling is false by default and will save all images in numerical order (first 5 images using the first config and then 10 images using the second config).
debugLogs: If you want to have logs to debug and see what is happening when you generate images, you can set the variable
debugLogsto true. It is false by default, so you will only see general logs.
In this part you can specify output image width and height sizes in pixel
If you want .gif outputs, you can set
exportto true, and
repeatis the number of cycles in each .gif animation.
repeat: -1will produce a one-time render and
repeat: 0will loop forever.
You can specify the quality you want for your gif animations. A higher-quality means larger filesizes. You can specify the delay in milliseconds before the animation starts in the .gif.
If you want to change the ratio of the pixels then you can update the ratio property. The lower the number on the left, the more pixelated the image will be.
If you want to add any extra metadata to your collection you can put it inside
extraMetadataobject. For example:
First, you need to install dependencies for this engine. Open a terminal and make sure you’re at hashlips_art_engine directory and run
First, you need to install the dependencies for the hashlips engine. Open a terminal and make sure you’re in the
hashlips_art_enginedirectory and run
To generate images using the layers and metadata you have set up, run
yarn run generate:
Awesome! now you have your images in the
hashlips_art_engine/build/imagesfolder, and their metadata inside the
hashlips_art_engine/build/jsonfolder. Check them out! Here are my 5 generated images altogether:
In the next section, we will upload our assets to Arweave and we will create a candy machine for minting our NFTs.
We will use candy-machine-cli to upload our images to the Arweave and create a minting machine for our NFTs.
Candy Machine is a tool built by Metaplex and Solana for uploading NFT assets to arweave and building a minting machine program on Solana For NFTs.
In this tutorial, we are using it to upload the assets and create a minting machine for our NFTs.
If you open Arweave’s website you find this definition:
In simple words, Arweave enables you to store documents and applications permanently. Candy machine CLI uploads our assets to Arweave by default.
First, we need to create an
metaplex-masterrepository we cloned before. Copy all the images from the
hashlips_art_engine/build/imagesdirectory and paste them to the
metaplex-master/assetsfolder. Do the same thing with the metadata files from
hashlips_art_engine/build/jsonexcept for the
_metadata.jsonfile. Now in your assets folder, you should have both the images and metadata files as shown below:
Before using the candy-machine-cli, we need to install its dependencies and build an executable version. To do that, open a terminal in the
metaplex-master/jsdirectory. To install the dependencies, run
yarn install. It may take a few moments. You are done with installing candy-machine-cli and can return to the Metaplex project directory with
To upload our Assets to Arweave and create our candy machine first we need to configure the candy machine we want to create.
To configure a candy machine you need to create
config.jsonfile in your metaplex directory. In this file we can setup and customize our candy machine. A minimal, simple setup can be:
It is important to include all variables above in your
config.jsonbecause if you remove a variable with
nullvalue you would get an error while creating your candy machine.
price: Specifies the price in $SOL for minting each NFT
number: Number of NFTs in the Collection to be minted
gateKeeper: Since a candy machine is open for bot attacks, you can set this field to ask the user to solve a captcha before being able to mint an NFT.
solTreasuryAccount: SOL wallet to receive proceedings SOL payments
goLiveDate: Timestamp when minting is allowed after
Parameters explained above are fundamental ones to understand for creating a simple candy machine but this isn't always the use case. Maybe you're expecting a certain feature or you want to set an ending date for you launch or something else. For that there is a detailed documentation for different available variables to be used inside
In candy machine version 1 you needed to upload assets and create a candy machine in two separate cli commands. But in candy machine version 2 you can do both using command bellow:
-e: Environment you're using. Here we are using devnet
-k: Specifies the path to keypair which will pay for the fees of uploading. Here we are using the keypair we generated at beginning of the tutorial.
-cp: The path to candy machine configuration file
-c: The cache file suffix. This a suffix which will be added to a cache file generated after creating candy machine holding the information related to it.
./assets: The path to folder holding assets of the collection.
In your terminal make sure you’re in the metaplex-master directory then run the command. Now, your candy machine is created and you can find all of the information and details about it in a file created in the .cache folder. The filename will be different depending on the network you have chosen for creating your candy machine - for instance, if you have deployed on devnet it would be
<name of the network you’ve deployed your collection to>-temp
for instance, if you have deployed on devnet, it would be devnet-temp.
You will need some of this information later in configuring the candy machine dApp. Let's build a frontend connected to our candy machine so that users can mint our NFTs.
To build a minting website for your candy machine, you can use a frontend framework like react and build everything from scratch. But there are community boiler plate projects which provide all fundamental parts like connecting to solana, connecting wallet and etc. There is also a similar project "fair-launch" built by Metaplex. It comes with Metaplex repository you cloned. It is located at
js/packages/fair-launch. This project gives us a basic UI, we just need to customize it.
First, you need to install all the dependencies of this project. run
npm install. Before you start the frontend local host, you need to configure the project. We have a
.envfile inside the project directory with the content below:
REACT_APP_CANDY_MACHINE_IDthis takes your
candyMachineAddress, copy it from devnet-temp.json
- Remember to uncomment the lines
- Also comment out the lines
REACT_APP_SOLANA_RPC_HOST=https://trashpandas.rpcpool.comsince we are not deploying to Mainnet-beta!
REACT_APP_FAIR_LAUNCH_ID=is used for Phase 1 of the fair launch
To configure this file we need to use
npm startto run our dApp locally on localhost:3000.
You may ask why we launched it on devnet and not on mainnet-beta?! for two reasons:
- You can estimate the costs of launching on mainnet-beta
- You can make sure there aren't any bugs or errors stopping you in the middle of the process
From the UI aspect our app isn’t that good. So let’s add some styling to our app in the next section.
To customize the frontend you are free to do whatever you want. Here is a simple example on how you can Customize it:
Replace the CSS in
candy-machine-mint/src/index.csswith the CSS shown below. This adds a nice gradient background to our app.
From assets folder copy-paste
PhaseHeader.tsxfirst import the
0.pngfile you just added:
Then in the definition of
Headercomponent, replace the code below with the existing one. This removes status badge and includes a description about our NFT collection:
PhaseHeadercomponent definition, find the
phase === Phase.Unknown && !candyMachinepart and replace its code with code below. This removes description since you added it in code above and adds a title for the case when user hasn't connected their wallet yet.
phase === Phase.Phase4and replace its code with code below. It specifies the title to be used in
Now let’s mint an NFT in our nice looking app!
YaY, we did it! Let’s check out our newly minted NFT in our wallet:
You can deploy this project to your favorite hosting service like Firebase, Vercel or any other provider. I deployed it to Firebase and you can check it out here and mint your own NFT if there are any left 😉.
You successfully launched your collection on devnet and now you are ready to deploy to mainnet-beta. There isn't any significant difference between deploying to devnet and mainnet-beta. you need to switch back to mainnet-beta by running
solana config set --url mainnet-beta. this time we need to top our wallet up with real SOL. You can easily purchase some from an exchange like FTX.
The process of generating the assets works the same since it’s unrelated to the Solana network you are using.
In the tutorial where you are creating a candy machine and uploading the assets, you need to change
-e mainnet-betain the command.
To clarify, when deploying to mainnet-beta that command would look like this:
In the tutorial where you are configuring your fair-launch dApp, this time inside the
.cachefolder we would have
devnet-tempbut the structure of the two files is the same. Because this time we are launching on mainnet-beta, we need to set the
fair-launchfolder like below:
REACT_APP_CANDY_MACHINE_IDthis takes your
candyMachineAddress, copy it from mainnet-beta-temp.json
- Remember to uncomment the lines
- Also comment out the lines
REACT_APP_SOLANA_RPC_HOST=https://api.devnet.solana.comas we are not deploying to devnet!
REACT_APP_FAIR_LAUNCH_ID=is used for Phase 1 of the fair launch
That's All of the adjustments you need to make to launch your minting dApp on mainnet-beta.
In this tutorial, we learned how to create a collection of unique generative NFTs and then create a minting dApp for them. We went through steps below:
- We set up the Solana CLI.
- We created the layers for our NFT collection.
- We used Hashlips art engine for creating NFT assets from our layers.
- We uploaded NFT assets to Arweave using Metaplex "candy machine"
- We built a frontend for our Metaplex "candy machine" app using "fair-launch" React project.
I'm Mahdi Mostafavi a web developer and I'm learning about Solana. my GitHub: @mmostafavi
If you found any misinformation in the article or had any suggestions to improve the tutorial you can message me on Twitter: @mahdi_ftp.
hashlips art engine: https://github.com/HashLips/hashlips_art_engine
metaplex candy machine V2: (https://docs.metaplex.com/candy-machine-v2
NFT collection assets: https://bit.ly/3EYmc5X