<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ NFT - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ NFT - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Tue, 25 Aug 2026 10:12:14 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/nft/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Make an NFT in 14 Lines of Code ]]>
                </title>
                <description>
                    <![CDATA[ By Nico If you're a developer who's interested in Blockchain development, you should know something about NFTs, or Non-Fungible Tokens. So in this article, we'll learn about the engineering behind them so you can start building your own. At the end o... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-make-an-nft/</link>
                <guid isPermaLink="false">66d46040ffe6b1f641b5fa32</guid>
                
                    <category>
                        <![CDATA[ Blockchain ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Ethereum ]]>
                    </category>
                
                    <category>
                        <![CDATA[ NFT ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Thu, 14 Oct 2021 17:49:36 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/10/nft.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Nico</p>
<p>If you're a developer who's interested in Blockchain development, you should know something about NFTs, or Non-Fungible Tokens. So in this article, we'll learn about the engineering behind them so you can start building your own.</p>
<p>At the end of the project, you will have your own Ethereum wallet with a new NFT in it. This tutorial is beginner-friendly and does not require any prior knowledge of the Ethereum network or smart contracts. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/10/image-46.png" alt="Image" width="600" height="400" loading="lazy">
<em>The NFT contract has only 14 lines of code</em></p>
<h2 id="heading-what-is-an-nft">What is an NFT?</h2>
<p>NFT stands for non-fungible token. <a target="_blank" href="https://ethereum.org/en/nft/">This quote from ethereum.org</a> explains it well:</p>
<blockquote>
<p>NFTs are tokens that we can use to represent ownership of unique items. They let us tokenise things like art, collectibles, even real estate. They can only have one official owner at a time and they're secured by the Ethereum blockchain – no one can modify the record of ownership or copy/paste a new NFT into existence.</p>
</blockquote>
<h2 id="heading-what-is-an-nft-standard-or-erc-721">What is an NFT standard or ERC-721?</h2>
<p>The ERC-721 is the most common NFT standard. If your Smart Contract implements certain standardized API methods, it can be called an ERC-721 Non-Fungible Token Contract. </p>
<p>These methods are specified in the <a target="_blank" href="https://eips.ethereum.org/EIPS/eip-721">EIP-721</a>. Open-sourced projects like OpenZeppelin have simplified the development process by implementing the most common ERC standards as a reusable library. </p>
<h2 id="heading-what-is-minting-an-nft">What is minting an NFT?</h2>
<p>By minting an NFT, you publish a unique token on a blockchain. This token is an instance of your Smart Contract. </p>
<p>Each token has a unique tokenURI, which contains metadata of your asset in a JSON file that conforms to certain schema. The metadata is where you store information about your NFT, such as name, image, description, and other attributes.</p>
<p>An example of the JSON file for the "ERC721 Metadata Schema" looks like this:</p>
<pre><code class="lang-json">{
    <span class="hljs-attr">"attributes"</span>: [
        {
            <span class="hljs-attr">"trait_type"</span>: <span class="hljs-string">"Shape"</span>,
            <span class="hljs-attr">"value"</span>: <span class="hljs-string">"Circle"</span>
        },
        {
            <span class="hljs-attr">"trait_type"</span>: <span class="hljs-string">"Mood"</span>,
            <span class="hljs-attr">"value"</span>: <span class="hljs-string">"Sad"</span>
        }
    ],
    <span class="hljs-attr">"description"</span>: <span class="hljs-string">"A sad circle."</span>,
    <span class="hljs-attr">"image"</span>: <span class="hljs-string">"https://i.imgur.com/Qkw9N0A.jpeg"</span>,
    <span class="hljs-attr">"name"</span>: <span class="hljs-string">"Sad Circle"</span>
}
</code></pre>
<h2 id="heading-how-do-i-store-my-nfts-metadata">How do I store my NFT's metadata?</h2>
<p>There are three main ways to store an NFT's metadata. </p>
<p>First, you can store the information on-chain. In other word, you can extend your ERC-721 and store the metadata on the blockchain, which can be costly. </p>
<p>The second method is to use <a target="_blank" href="https://docs.ipfs.io/concepts/what-is-ipfs/">IPFS</a>. And the third way is to simply have your API return the JSON file.</p>
<p>The first and second methods are usually preferred, since you cannot temper the underlying JSON file. For the scope of this project, we will opt for the third method. </p>
<p>For a good tutorial on using NFTs with IPFS, read <a target="_blank" href="https://docs.alchemy.com/alchemy/tutorials/how-to-create-an-nft/how-to-mint-a-nft#step-4-configure-the-metadata-for-your-nft-using-ipfs">this article</a> by the Alchemy team.</p>
<h2 id="heading-what-well-be-building">What We'll Be Building</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/10/emotionalshapes.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>In this tutorial, we'll be creating and minting our own NFT. It is beginner-friendly and does not require any prior knowledge of the Ethereum network or smart contracts. Still, having a good grasp on those concepts will help you understand what is going on behind the scenes. </p>
<p>In an upcoming tutorial, we'll build a fully-functional React web app where you can display and sell your NFTs.</p>
<p>If you are just getting started with dApp development, begin by reading through <a target="_blank" href="https://ethereum.org/en/developers/docs/intro-to-ethereum/">the key topics</a> and watch this <a target="_blank" href="https://www.youtube.com/watch?v=M576WGiDBdQ">amazing course</a> by Patrick Collins.</p>
<p><em>This project is intentionally written with easily understandable code and is not suitable for production usage.</em> </p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<h3 id="heading-metamask">Metamask</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/10/image-32.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>We need an Ethereum address to interact with our Smart Contract. We will be using <a target="_blank" href="https://metamask.io/">Metamask</a> as our wallet. It is a free virtual wallet that manages your Ethereum addresses. We will need it to send and receive transactions (read more on that <a target="_blank" href="https://ethereum.org/en/developers/docs/transactions/">here</a>). For example, minting an NFT is a transaction. </p>
<p>Download their Chrome extension and their mobile app. We will need both as the Chrome extension does not display your NFTs.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/10/image-34.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Make sure to change the network to "Ropsten Test Network" for development purposes. You will need some Eth to cover the fees of deploying and minting your NFT. Head to the <a target="_blank" href="https://faucet.ropsten.be/">Ropsten Ethereum Faucet</a> and enter your address. You should soon see some test Eth in your Metamask account.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/10/image-35.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-alchemy">Alchemy</h3>
<p>To interact with the Ethereum Network, you will need to be connected to an Ethereum Node. </p>
<p>Running your own Node and maintaining the infrastructure is a project on its own. Luckily, there are nodes-as-a-service providers which host the infrastructure for you. There are many choices like Infura, BlockDaemon, and Moralis. We will be using <a target="_blank" href="https://www.alchemy.com/">Alchemy</a> as our node provider. </p>
<p>Head over to their website, create an account, choose Ethereum as your network and create your app. Choose Ropsten as your network.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/10/image-36.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>On your dashboard, click "view details" on your app, then click "view key". Save your http key somewhere as we will need that later.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/10/image-38.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-nodejsnpm">NodeJS/NPM</h3>
<p>We will be using NodeJS for the project. If you don't have it installed, <a target="_blank" href="https://www.freecodecamp.org/news/how-to-install-node-in-your-machines-macos-linux-windows/">follow this simple tutorial</a> by freeCodeCamp.</p>
<h2 id="heading-initialize-the-project">Initialize the project</h2>
<p>In your terminal, run this command to make a new directory for your project:</p>
<pre><code>mkdir nft-project
cd nft-project
</code></pre><p>Now, let's make another directory, <code>ethereum/</code>, inside <code>nft-project/</code> and initialize it with <a target="_blank" href="https://hardhat.org/getting-started/">Hardhat</a>. Hardhat is a dev tool that makes it easy to deploy and test your Ethereum software.</p>
<pre><code>mkdir ethereum
cd ethereum
npm init
</code></pre><p>Answer the questions however you want. Then, run those commands to make a Hardhat project:</p>
<pre><code>npm install --save-dev hardhat
npx hardhat
</code></pre><p>You will see this prompt:</p>
<pre><code><span class="hljs-number">888</span>    <span class="hljs-number">888</span>                      <span class="hljs-number">888</span> <span class="hljs-number">888</span>               <span class="hljs-number">888</span>
<span class="hljs-number">888</span>    <span class="hljs-number">888</span>                      <span class="hljs-number">888</span> <span class="hljs-number">888</span>               <span class="hljs-number">888</span>
<span class="hljs-number">888</span>    <span class="hljs-number">888</span>                      <span class="hljs-number">888</span> <span class="hljs-number">888</span>               <span class="hljs-number">888</span>
<span class="hljs-number">8888888888</span>  <span class="hljs-number">8888</span>b.  <span class="hljs-number">888</span>d888 .d88888 <span class="hljs-number">88888</span>b.   <span class="hljs-number">8888</span>b.  <span class="hljs-number">888888</span>
<span class="hljs-number">888</span>    <span class="hljs-number">888</span>     <span class="hljs-string">"88b 888P"</span>  d88<span class="hljs-string">" 888 888 "</span><span class="hljs-number">88</span>b     <span class="hljs-string">"88b 888
888    888 .d888888 888    888  888 888  888 .d888888 888
888    888 888  888 888    Y88b 888 888  888 888  888 Y88b.
888    888 "</span>Y888888 <span class="hljs-number">888</span>     <span class="hljs-string">"Y88888 888  888 "</span>Y888888  <span class="hljs-string">"Y888

Welcome to Hardhat v2.0.8

? What do you want to do? …
  Create a sample project
❯ Create an empty hardhat.config.js
  Quit</span>
</code></pre><p>Select create an empty hardhat.config.js. This will generate an empty <code>hardhat.config.js</code> file that we will later update.</p>
<p>For the web app, we will use <a target="_blank" href="https://nextjs.org/docs/getting-started">Next.js</a> to initialize a fully-functional web app. Go back to the root directory <code>nft-project/</code> and initialize a boilerplate Next.js app called web:</p>
<pre><code>cd ..
mkdir web
cd web
npx create-next-app@latest
</code></pre><p>Your project now looks like this:</p>
<pre><code>nft-project/
    ethereum/
    web/
</code></pre><p>Awesome! We are ready to dive into some real coding.</p>
<h2 id="heading-how-to-define-our-env-variables">How to Define Our .env Variables</h2>
<p>Remember the Alchemy key we grabbed from our test project earlier? We will use that along with our Metamask account's public and private keys to interact with the blockchain. </p>
<p>Run the following commands, make a file called <code>.env</code> inside your <code>ethereum/</code> directory, and install <a target="_blank" href="https://www.npmjs.com/package/dotenv">dotenv</a>. We will use them later.</p>
<pre><code>cd ..
cd ethereum
touch .env
npm install dotenv --save
</code></pre><p>For your <code>.env</code> file, put the key you have exported from Alchemy and <a target="_blank" href="https://metamask.zendesk.com/hc/en-us/articles/360015289632-How-to-Export-an-Account-Private-Key">follow those instructions</a> to grab your Metamask's private key.</p>
<p>Here's your .env file:</p>
<pre><code>DEV_API_URL = YOUR_ALCHEMY_KEY
PRIVATE_KEY = YOUR_METAMASK_PRIVATE_KEY
PUBLIC_KEY = YOUR_METAMASK_ADDRESS
</code></pre><h2 id="heading-the-smart-contract-for-nfts">The Smart Contract for NFTs</h2>
<p>Go to the <code>ethereum/</code> folder and create two more directories: contracts and scripts. <a target="_blank" href="https://hardhat.org/guides/project-setup.html">A simple hardhat project</a> contains those folders.</p>
<ul>
<li><code>contracts/</code> contains the source files of your contracts</li>
<li><code>scripts/</code> contains the scripts to deploy and mint our NFTs</li>
</ul>
<pre><code>mkdir contracts
mkdir scripts
</code></pre><p>Then, install OpenZeppelin. <a target="_blank" href="https://docs.openzeppelin.com/contracts/4.x/">OpenZeppelin Contract</a> is an open-sourced library with pre-tested reusable code to make smart contract development easier.</p>
<pre><code>npm install @openzeppelin/contracts
</code></pre><p>Finally, we will be writing the Smart Contract for our NFT. Navigate to your contracts directory and create a file titled <code>EmotionalShapes.sol</code>. You can name your NFTs however you see fit.</p>
<p>The <code>.sol</code> extension refers to the Solidity language, which is what we will use to program our Smart Contract. We will only be writing 14 lines of code with Solidity, so no worries if you haven't seen it before. </p>
<p>Start with <a target="_blank" href="https://ethereum.org/en/developers/docs/smart-contracts/languages/">this article</a> to learn more about Smart Contract languages. You can also directly jump to this Solidity <a target="_blank" href="https://reference.auditless.com/cheatsheet/">cheat sheet</a> which contains the main syntax.</p>
<pre><code>cd contracts
touch EmotionalShapes.sol
</code></pre><p>This is our Smart Contract:</p>
<pre><code class="lang-solidity"><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.8.0;</span>

<span class="hljs-keyword">import</span> <span class="hljs-string">"@openzeppelin/contracts/token/ERC721/ERC721.sol"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"@openzeppelin/contracts/utils/Counters.sol"</span>;

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">EmotionalShapes</span> <span class="hljs-keyword">is</span> <span class="hljs-title">ERC721</span> </span>{
    <span class="hljs-keyword">using</span> <span class="hljs-title">Counters</span> <span class="hljs-title"><span class="hljs-keyword">for</span></span> <span class="hljs-title">Counters</span>.<span class="hljs-title">Counter</span>;
    Counters.Counter <span class="hljs-keyword">private</span> _tokenIdCounter;

    <span class="hljs-function"><span class="hljs-keyword">constructor</span>(<span class="hljs-params"></span>) <span class="hljs-title">ERC721</span>(<span class="hljs-params"><span class="hljs-string">"EmotionalShapes"</span>, <span class="hljs-string">"ESS"</span></span>) </span>{}

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">_baseURI</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">internal</span></span> <span class="hljs-title"><span class="hljs-keyword">pure</span></span> <span class="hljs-title"><span class="hljs-keyword">override</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">string</span> <span class="hljs-keyword">memory</span></span>) </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-string">"YOUR_API_URL/api/erc721/"</span>;
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">mint</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> to</span>)
        <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint256</span></span>)
    </span>{
        <span class="hljs-built_in">require</span>(_tokenIdCounter.current() <span class="hljs-operator">&lt;</span> <span class="hljs-number">3</span>); 
        _tokenIdCounter.increment();
        _safeMint(to, _tokenIdCounter.current());

        <span class="hljs-keyword">return</span> _tokenIdCounter.current();
    }
}
</code></pre>
<p>Let's go through the code and understand what is going on. </p>
<ol>
<li>At the top of the file, we specified which OpenZeppelin module to import. We need the ERC721 contract as it is the 'base' of our Smart Contract. It has already implemented all the methods specified in <a target="_blank" href="https://eips.ethereum.org/EIPS/eip-721">EIP-721</a> so we can safely use it.</li>
<li>A Counter is useful to generate incremental ids for our NFTs. We named the variable <code>_tokenIdCounter</code></li>
<li>In the constructor, we initialized our ERC721 with its name and its symbol. I chose EmotionalShapes and ESS.</li>
<li>We override the default <code>_baseURI</code> function by returning our own. We will get to build that in a second. In summary, it is the URL that will be added as 'prefix' to all our tokenURIs. In the above example, the metadata of our NFTs will live in a JSON file at <code>YOUR_API_URL/[api/erc721/](https://e110-99-121-58-31.ngrok.io/api/erc721/)1</code>.</li>
<li>We implement the 'mint' function. It is the function that lets you publish an instance of this Smart Contract on the blockchain. I required the <code>_tokenIdCounter</code> variable to be less than 3 as I will only create three instances of my NFT. You can remove that if you want to mint more.</li>
<li>Finally, inside the mint function, we increment the <code>_tokenIdCounter</code> variable by 1, so our id will be 1, followed by 2, followed by 3. Then, we call the function provided by OpenZeppelin <code>_safeMint</code> to publish the token.</li>
</ol>
<p>Don't worry if you feel lost. You can attend a workshop led by volunteers from freeCodeCamp, where we invite devs of similar skill levels to build stuff together, including this NFT project. </p>
<p>The events are free and remote, so you can ask any questions directly. You can register <a target="_blank" href="https://equia.io">here</a>. The seats are limited so you will be invited to the next available events.</p>
<h2 id="heading-how-to-build-the-metadata-for-our-nft">How to Build the Metadata for our NFT</h2>
<p>As mentioned earlier, there are three main ways of storing your tokenURI. We will be building a simple API endpoint which resolve in our NFT's information as JSON. </p>
<p>Our Next.js project gives us a handy way to develop API routes. Go to the <code>web/</code> folder, find the <code>api/</code> folder within the <code>pages/</code> folder, and make our dynamic <code>[id].js</code> route in a <code>erc721/</code> folder (read more about routing <a target="_blank" href="https://www.freecodecamp.org/news/p/18513919-9e93-4ab3-9f52-2448aafa8835/develop%20API%20routes">here</a>):</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// web/pages/api/erc721/[id].js</span>

<span class="hljs-keyword">const</span> metadata = {
  <span class="hljs-number">1</span>: {
    <span class="hljs-attr">attributes</span>: [
      {
        <span class="hljs-attr">trait_type</span>: <span class="hljs-string">"Shape"</span>,
        <span class="hljs-attr">value</span>: <span class="hljs-string">"Circle"</span>,
      },
      {
        <span class="hljs-attr">trait_type</span>: <span class="hljs-string">"Mood"</span>,
        <span class="hljs-attr">value</span>: <span class="hljs-string">"Sad"</span>,
      },
    ],
    <span class="hljs-attr">description</span>: <span class="hljs-string">"A sad circle."</span>,
    <span class="hljs-attr">image</span>: <span class="hljs-string">"https://i.imgur.com/Qkw9N0A.jpeg"</span>,
    <span class="hljs-attr">name</span>: <span class="hljs-string">"Sad Circle"</span>,
  },
  <span class="hljs-number">2</span>: {
    <span class="hljs-attr">attributes</span>: [
      {
        <span class="hljs-attr">trait_type</span>: <span class="hljs-string">"Shape"</span>,
        <span class="hljs-attr">value</span>: <span class="hljs-string">"Rectangle"</span>,
      },
      {
        <span class="hljs-attr">trait_type</span>: <span class="hljs-string">"Mood"</span>,
        <span class="hljs-attr">value</span>: <span class="hljs-string">"Angry"</span>,
      },
    ],
    <span class="hljs-attr">description</span>: <span class="hljs-string">"An angry rectangle."</span>,
    <span class="hljs-attr">image</span>: <span class="hljs-string">"https://i.imgur.com/SMneO6k.jpeg"</span>,
    <span class="hljs-attr">name</span>: <span class="hljs-string">"Angry Rectangle"</span>,
  },
  <span class="hljs-number">3</span>: {
    <span class="hljs-attr">attributes</span>: [
      {
        <span class="hljs-attr">trait_type</span>: <span class="hljs-string">"Shape"</span>,
        <span class="hljs-attr">value</span>: <span class="hljs-string">"Triangle"</span>,
      },
      {
        <span class="hljs-attr">trait_type</span>: <span class="hljs-string">"Mood"</span>,
        <span class="hljs-attr">value</span>: <span class="hljs-string">"Bored"</span>,
      },
    ],
    <span class="hljs-attr">description</span>: <span class="hljs-string">"An bored triangle."</span>,
    <span class="hljs-attr">image</span>: <span class="hljs-string">"https://i.imgur.com/hMVRFoJ.jpeg"</span>,
    <span class="hljs-attr">name</span>: <span class="hljs-string">"Bored Triangle"</span>,
  },
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handler</span>(<span class="hljs-params">req, res</span>) </span>{
  res.status(<span class="hljs-number">200</span>).json(metadata[req.query.id] || {});
}
</code></pre>
<p>For the sake of this project, I made the code as easily understandable as possible. This is definitely not suited for production (please don't use an Imgur url for your NFT). Make sure to define the metadata for all the NFTs that you intend to mint.</p>
<p>Now, go to the web directory, and start your Next.js app with this command:</p>
<pre><code>npm run dev
</code></pre><p>Your app should be running on localhost:3000. To make sure our endpoint works, go to <a target="_blank" href="http://localhost:3000/api/erc721/1">http://localhost:3000/api/erc721/1</a> and it should resolve with a JSON object of your first NFT's metadata.</p>
<h2 id="heading-how-to-expose-the-metadata-for-our-nft">How to Expose the Metadata for our NFT</h2>
<p>Since your app is hosted locally, other apps cannot access it. Using a tool like <a target="_blank" href="https://ngrok.com/">ngrok</a>, we can expose our local host to a publicly accessible URL.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/10/image-39.png" alt="Image" width="600" height="400" loading="lazy"></p>
<ol>
<li>Go to <a target="_blank" href="https://ngrok.com/">ngrok.com</a> and complete the registration process</li>
<li>Unzip the downloaded package</li>
<li>In your terminal, make sure you cd into the folder where you unzipped your ngrok package</li>
<li>Follow the instruction on your dashboard and run</li>
</ol>
<pre><code>./ngrok authtoken YOUR_AUTH_TOKEN
</code></pre><ol start="5">
<li>Then, run this command to create a tunnel to your web app hosted on localhost:3000</li>
</ol>
<pre><code>./ngrok http <span class="hljs-number">3000</span>
</code></pre><ol start="6">
<li>You are almost there! On your terminal, you should see something like this:</li>
</ol>
<pre><code>ngrok by @inconshreveable                                                                            (Ctrl+C to quit)

Session Status                online                                                                                 
Account                       YOUR_ACCOUNT (Plan: Free)                                                                       
Version                       <span class="hljs-number">2.3</span><span class="hljs-number">.40</span>                                                                                 
Region                        United States (us)                                                                     
Web Interface                 http:<span class="hljs-comment">//127.0.0.1:4040                                                                  </span>
Forwarding                    http:<span class="hljs-comment">//YOUR_NGROK_ADDRESS -&gt; http://localhost:3000                             </span>
Forwarding                    https:<span class="hljs-comment">//YOUR_NGROK_ADDRESS -&gt; http://localhost:3000</span>
</code></pre><p>Go to <code>YOUR_NGROK_ADDRESS/api/erc721/1</code> to make sure your endpoint works correctly.</p>
<h2 id="heading-how-to-deploy-our-nft">How to Deploy our NFT</h2>
<p>Now that we have done all the ground work (oof), let's go back to our <code>ethereum/</code> folder and get ready to deploy our NFT.</p>
<p>Change the <code>_baseURI</code> function in your <code>ethreum/contracts/YOUR_NFT_NAME.sol</code> file to return your ngrok address.</p>
<pre><code><span class="hljs-comment">// ethereum/conrtacts/EmotionalShapes.sol</span>

contract EmotionalShapes is ERC721 {
...
    function _baseURI() internal pure override returns (string memory) {
        <span class="hljs-keyword">return</span> <span class="hljs-string">"https://YOUR_NGROK_ADDRESS/api/erc721/"</span>;
    }
...
}
</code></pre><p>To deploy our NFT, we will first need to <a target="_blank" href="https://hardhat.org/guides/compile-contracts.html">compile it using Hardhat</a>. To make the process easier, we will install <a target="_blank" href="https://docs.ethers.io/v5/">ethers.js</a>.</p>
<pre><code>npm install @nomiclabs/hardhat-ethers --save-dev
</code></pre><p>Let's update our hardhat.config.js:</p>
<pre><code><span class="hljs-built_in">require</span>(<span class="hljs-string">"dotenv"</span>).config();
<span class="hljs-built_in">require</span>(<span class="hljs-string">"@nomiclabs/hardhat-ethers"</span>);

<span class="hljs-built_in">module</span>.exports = {
  <span class="hljs-attr">solidity</span>: <span class="hljs-string">"0.8.0"</span>,
  <span class="hljs-attr">defaultNetwork</span>: <span class="hljs-string">"ropsten"</span>,
  <span class="hljs-attr">networks</span>: {
    <span class="hljs-attr">hardhat</span>: {},
    <span class="hljs-attr">ropsten</span>: {
      <span class="hljs-attr">url</span>: process.env.DEV_API_URL,
      <span class="hljs-attr">accounts</span>: [<span class="hljs-string">`0x<span class="hljs-subst">${process.env.PRIVATE_KEY}</span>`</span>],
    },
  },
};
</code></pre><p>To learn more about the hardhat configuration file, take a look at their <a target="_blank" href="https://hardhat.org/config/">documentation</a>. We have configured the ropsten network with our Alchemy URL and provided it with the private key of your metamask account.</p>
<p>Finally, run:</p>
<pre><code>npx hardhat compile
</code></pre><p>This lets hardhat generate two files per compiled contract. We should see a newly created <code>artifacts/</code> folder that contains your compiled contracts in the <code>contracts/</code> folder. To learn more about how that works, read <a target="_blank" href="https://hardhat.org/guides/compile-contracts.html">this tutorial</a> by the Hardhat team.</p>
<p>Now, let's write a script to finally deploy our NFT to the test network. In your <code>scripts/</code> folder, create a file called <code>deploy.js</code>.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// ethereum/scripts/deploy.js</span>

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">main</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> EmotionalShapes = <span class="hljs-keyword">await</span> ethers.getContractFactory(<span class="hljs-string">"EmotionalShapes"</span>);
  <span class="hljs-keyword">const</span> emotionalShapes = <span class="hljs-keyword">await</span> EmotionalShapes.deploy();

  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"EmotionalShapes deployed:"</span>, emotionalShapes.address);
}

main()
  .then(<span class="hljs-function">() =&gt;</span> process.exit(<span class="hljs-number">0</span>))
  .catch(<span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> {
    <span class="hljs-built_in">console</span>.error(error);
    process.exit(<span class="hljs-number">1</span>);
  });
</code></pre>
<p>This code is inspired by <a target="_blank" href="https://hardhat.org/guides/deploying.html">the hardhat deployment tutorial</a>.</p>
<blockquote>
<p>A <code>ContractFactory</code> in ethers.js is an abstraction used to deploy new smart contracts, so <code>EmotionalShapes</code> here is a factory for instances of our token contract. Calling <code>deploy()</code> on a <code>ContractFactory</code> will start the deployment, and return a <code>Promise</code> that resolves to a <code>Contract</code>. This is the object that has a method for each of your smart contract functions.</p>
</blockquote>
<h3 id="heading-how-to-view-the-nft-on-the-blockchain">How to view the NFT on the blockchain</h3>
<p>Run the deployment script:</p>
<pre><code>node ./scripts/deploy.js
</code></pre><p>You should see in your terminal <code>EmotionalShapes deployed: SOME_ADDRESS</code>. This is the address where your Smart Contract is deployed on the ropsten test network.</p>
<p>If you head over to <code>https://ropsten.etherscan.io/address/SOME_ADDRESS</code>, you should see your freshly deployed NFT. Yes! You did it!</p>
<p>If you are stuck somewhere in the tutorial or feeling lost, again, you can <a target="_blank" href="https://equia.io">join our live workshops</a> where we will build this project together in a Zoom call. </p>
<h2 id="heading-how-to-mint-your-nft">How to Mint your NFT</h2>
<p>Now that you have deployed your NFT, it's time to mint it for yourself! Create a new file called <code>mint.js</code> in your scripts/ folder. We will be using ethers.js to help us.</p>
<p>Start by adding the <code>ethers.js</code> package:</p>
<pre><code>npm install --save ethers
</code></pre><p>Then, populate the <code>mint.js</code> file:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">require</span>(<span class="hljs-string">"dotenv"</span>).config();
<span class="hljs-keyword">const</span> { ethers } = <span class="hljs-built_in">require</span>(<span class="hljs-string">"ethers"</span>);

<span class="hljs-keyword">const</span> contract = <span class="hljs-built_in">require</span>(<span class="hljs-string">"../artifacts/contracts/EmotionalShapes.sol/EmotionalShapes.json"</span>);
<span class="hljs-keyword">const</span> contractInterface = contract.abi;

<span class="hljs-comment">// https://docs.ethers.io/v5/api/providers</span>
<span class="hljs-keyword">const</span> provider = ethers.getDefaultProvider(<span class="hljs-string">"ropsten"</span>, {
  <span class="hljs-attr">alchemy</span>: process.env.DEV_API_URL,
});

<span class="hljs-comment">// https://docs.ethers.io/v5/api/signer/#Wallet</span>
<span class="hljs-keyword">const</span> wallet = <span class="hljs-keyword">new</span> ethers.Wallet(process.env.PRIVATE_KEY, provider);

<span class="hljs-comment">//https://docs.ethers.io/v5/api/contract/contract</span>
<span class="hljs-keyword">const</span> emotionalShapes = <span class="hljs-keyword">new</span> ethers.Contract(
  YOUR_NFT_ADDRESS,
  contractInterface,
  wallet
);

<span class="hljs-keyword">const</span> main = <span class="hljs-function">() =&gt;</span> {
  emotionalShapes
    .mint(process.env.PUBLIC_KEY)
    .then(<span class="hljs-function">(<span class="hljs-params">transaction</span>) =&gt;</span> <span class="hljs-built_in">console</span>.log(transaction))
    .catch(<span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"something went wrong"</span>, e));
};

main();
</code></pre>
<p>I have left comments to where you can find more information about the different methods. We first grab the contract's interface (ABI). From ethereum.org:</p>
<blockquote>
<p>An application binary interface, or ABI, is the standard way to interact with <a target="_blank" href="https://ethereum.org/en/glossary/#contract-account">contracts</a> in the Ethereum ecosystem, both from outside the blockchain and for contract-to-contract interactions.</p>
</blockquote>
<p>Your ABI defines how others interact with your contract. Then, we created our provider with Alchemy (remember about node-as-a-service). Finally, we initialize our wallet with our private key.</p>
<p>The <code>main()</code> function calls the <code>mint</code> method in the Smart Contract we had just deployed. The <code>mint</code> method takes only one parameter, <code>to</code>, which indicate the receiver of the token. Since we are minting for ourself, we put the public address of our Metamask account.</p>
<p>If everything goes well, you should see the transaction logged in your terminal. Grab the <code>hash</code> property and go to <code>https://ropsten.etherscan.io/tx/YOUR_HASH</code>. You should see the minting transaction there!</p>
<h2 id="heading-how-to-view-the-nft-in-your-metamask-wallet">How to View the NFT in your Metamask Wallet</h2>
<p>You need to start by downloading the mobile version of Metamask. Then, log into your account. </p>
<p>You should see an NFTs tab along with an add NFT button. Click on the button and enter the address of your Smart Contract along with the ids that you have minted. If you have followed the tutorial, you should start with an id of <code>1</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/10/IMG_0376.jpeg" alt="Image" width="600" height="400" loading="lazy">
<em>View NFTs in your Metamask wallet</em></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Congratulations! You have just minted your own NFT. In the next part of the project, we will be building the front end React app to interact with our contract. The end goal is to build a fully functional web app where you can sell your own NFTs.</p>
<p>Lastly, you can <a target="_blank" href="https://equia.io">join our live workshops</a> with volunteers from freeCodeCamp where we will build this project together with other developers. </p>
<p>The events are free for everyone across the world and invitations are sent first-come, first-serve. If you'd like to lead the workshops, DM me <a target="_blank" href="https://twitter.com/aly4alyssa">on Twitter</a>, we'd love to have you! We also organize other type of events like hiring fairs and social meetups. </p>
<p>Let me know what you want to build. NFTs are still in its infancy and novel ideas are more than welcome. Can't wait to see what crazy idea you have!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Solidity Tutorial – How to Create NFTs with Hardhat ]]>
                </title>
                <description>
                    <![CDATA[ I'm a developer who's mostly been writing JavaScript, so the Solidity development environment was a bit hard to learn.  About four months ago, I switched to Hardhat from Truffle. This cool new kid on the block drastically improved my coding experienc... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/solidity-tutorial-hardhat-nfts/</link>
                <guid isPermaLink="false">66b99a2f9aaac6f19de58aff</guid>
                
                    <category>
                        <![CDATA[ Blockchain ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Ethereum ]]>
                    </category>
                
                    <category>
                        <![CDATA[ NFT ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Smart Contracts ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Solidity ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Taisuke Mino ]]>
                </dc:creator>
                <pubDate>Mon, 17 May 2021 14:39:55 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/05/hardhat_nft-1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>I'm a developer who's mostly been writing JavaScript, so the Solidity development environment was a bit hard to learn. </p>
<p>About four months ago, I switched to <a target="_blank" href="https://hardhat.org/">Hardhat</a> from Truffle. This cool new kid on the block drastically improved my coding experience. So today I want to share it with my fellow Solidity developers.</p>
<p>In this post, I will walk you through the initial set-up, compilation, testing, debugging, and finally deployment.</p>
<p>At the end of this post, you will be able understand how to deploy an NFT contract to the local network with Hardhat. </p>
<p>The goal of this post is to make you familiar with Hardhat. I won’t talk about how to write a test or Solidity syntax. However, you should be able to follow along without any Solidity knowledge if you know how to write JavaScript.</p>
<p>See <a target="_blank" href="https://github.com/taisukemino/hardhat-nft-tutorial">this repo</a> for the code.</p>
<h2 id="heading-how-to-set-up-the-project">How to Set Up the Project</h2>
<p>Let’s start an npm project first:</p>
<pre><code>npm init --yes
</code></pre><p>Then install the Hardhat package:</p>
<pre><code>npm install --save-dev hardhat
</code></pre><p>Cool! Now you are ready to create a new Hardhat project:</p>
<pre><code>npx hardhat
</code></pre><p>Choose <code>Create an empty hardhat.config.js</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/05/image-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>This will create <code>hardhat.config.js</code> in your root directory with the solidity compiler version specified:</p>
<pre><code class="lang-js"><span class="hljs-comment">/**
 * <span class="hljs-doctag">@type </span>import('Hardhat/config').HardhatUserConfig
 */</span>
<span class="hljs-built_in">module</span>.exports = {
  <span class="hljs-attr">solidity</span>: <span class="hljs-string">"0.7.3"</span>,
};
</code></pre>
<h2 id="heading-how-to-write-and-compile-the-contract">How to Write and Compile the Contract</h2>
<p>All right, we will start writing a simple contract and then we'll compile it.</p>
<p>Make a new Solidity file within a new <code>contracts</code> directory:</p>
<pre><code> mkdir contracts &amp;&amp; cd contracts &amp;&amp; touch MyCryptoLions.sol
</code></pre><p>We'll use the open-zeppelin package to write our NFT contract. So first, install the open-zeppelin package:</p>
<pre><code>npm install --save-dev @openzeppelin/contracts
</code></pre><p>Here is the contract code we will be compiling:</p>
<pre><code class="lang-solidity"><span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.7.3;</span>

<span class="hljs-keyword">import</span> <span class="hljs-string">"@openzeppelin/contracts/token/ERC721/ERC721.sol"</span>;

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">MyCryptoLions</span> <span class="hljs-keyword">is</span> <span class="hljs-title">ERC721</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">constructor</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> <span class="hljs-keyword">memory</span> name, <span class="hljs-keyword">string</span> <span class="hljs-keyword">memory</span> symbol</span>)
        <span class="hljs-title">ERC721</span>(<span class="hljs-params">name, symbol</span>)
    </span>{}
}
</code></pre>
<p>The first thing you need to do in any solidity file is to declare the compiler version. Then we can import the ERC721 contract (NFT contract) from open-zeppelin just like you do in JavaScript.</p>
<p>Solidity is a contract-oriented language. Just like an object-oriented language, contracts can have members such as functions and variables. In our code, we have only the constructor, which will be called when we deploy our contract.</p>
<p>Our contract inherits the ERC721 and then passes the <code>name</code> and <code>symbol</code> arguments which are going to be passed to the ERC721 contract. They literally decide the name and symbol of your NFT token.</p>
<p>We will pass whatever values we want to <code>name</code> and <code>symbol</code> at the point of deployment.</p>
<p>To compile it, run:</p>
<pre><code>npx hardhat compile
</code></pre><p>You might get some warnings but we'll ignore them to keep things simple. You should see <code>Compilation finished successfully</code> at the bottom.</p>
<p>You should also notice that the <code>/arfifacts</code> and <code>/cache</code> directories were generated. You don’t have to worry about them for this post, but it’s good to keep in mind that you can use <code>abi</code> in the artifacts if you want to interact with the contract when you build the frontend.</p>
<h2 id="heading-how-to-test-the-contract">How to Test the Contract</h2>
<p>Since smart contracts are mostly financial applications – and they're also hard to change – testing is critical.</p>
<p>We will use some packages for testing. Install with the command below:</p>
<pre><code>npm install --save-dev @nomiclabs/hardhat-waffle ethereum-waffle chai @nomiclabs/hardhat-ethers ethers
</code></pre><p><code>ethereum-waffle</code> is a testing framework for smart contracts. <code>chai</code> is an assertion library. We'll write tests in waffle using Mocha alongside Chai. <code>ethers.js</code> is a JavaScript SDK for interacting with the Ethereum blockchain. The other two packages are plugins for Hardhat.</p>
<p>Now, let’s make a new directory <code>test</code> in the root directory and make a new file called <code>test.js</code> in it:</p>
<pre><code>mkdir test &amp;&amp; cd test &amp;&amp; touch test.js
</code></pre><p>Make sure you require <code>@nomiclabs/hardhat-ethers</code> in the <code>hardhat.config.js</code> to make it available everywhere:</p>
<pre><code><span class="hljs-built_in">require</span>(<span class="hljs-string">"@nomiclabs/hardhat-ethers"</span>);
</code></pre><p>Here is a simple test:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> { expect } = <span class="hljs-built_in">require</span>(<span class="hljs-string">"chai"</span>);

describe(<span class="hljs-string">"MyCryptoLions"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
  it(<span class="hljs-string">"Should return the right name and symbol"</span>, <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">const</span> MyCryptoLions = <span class="hljs-keyword">await</span> hre.ethers.getContractFactory(<span class="hljs-string">"MyCryptoLions"</span>);
    <span class="hljs-keyword">const</span> myCryptoLions = <span class="hljs-keyword">await</span> MyCryptoLions.deploy(<span class="hljs-string">"MyCryptoLions"</span>, <span class="hljs-string">"MCL"</span>);

    <span class="hljs-keyword">await</span> myCryptoLions.deployed();
    expect(<span class="hljs-keyword">await</span> myCryptoLions.name()).to.equal(<span class="hljs-string">"MyCryptoLions"</span>);
    expect(<span class="hljs-keyword">await</span> myCryptoLions.symbol()).to.equal(<span class="hljs-string">"MCL"</span>);
  });
});
</code></pre>
<p>This code deploys our contract to the local Hardhat network and then checks if the <code>name</code> and <code>symbol</code> values are what we expect.</p>
<p>Run the test:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/05/image-2.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Awesome, it passed the test!</p>
<h3 id="heading-how-to-use-consolelog-in-hardhat">How to Use console.log() in Hardhat</h3>
<p>Now here is the coolest thing you can do with Hardhat. You can use <code>console.log()</code> just like you do in JavaScript, which was not possible before. <code>console.log()</code> alone is more than enough reason to switch to Hardhat. </p>
<p>Let’s go back to your solidity file and use <code>console.log()</code>.</p>
<pre><code>pragma solidity ^<span class="hljs-number">0.7</span><span class="hljs-number">.3</span>;

<span class="hljs-keyword">import</span> <span class="hljs-string">"@openzeppelin/contracts/token/ERC721/ERC721.sol"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"hardhat/console.sol"</span>;

contract MyCryptoLions is ERC721 {
    <span class="hljs-keyword">constructor</span>(string memory name, string memory symbol) ERC721(name, symbol) {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"name"</span>, name);
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"symbol"</span>, symbol);
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"msg.sender"</span>, msg.sender); <span class="hljs-comment">//msg.sender is the address that initially deploys a contract</span>
    }
}
</code></pre><p>And run the test again with <code>npx hardhat test</code>. Then the command will compile the contract again, and then run the test. You should be able to see some values logged from the contract.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/05/image-3.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>This makes debugging a lot easier for you.</p>
<p>One caveat is that it supports only these data types:</p>
<ul>
<li>uint</li>
<li>string</li>
<li>bool</li>
<li>address</li>
</ul>
<p>But other than that, you can use it as if you are writing JavaScript.</p>
<h2 id="heading-how-to-deploy-the-contract">How to Deploy the Contract</h2>
<p>All right! Now let’s deploy our contract. We can deploy our contract to one of the testing networks, the Mainnet, or even a mirrored version of the Mainnet in local. </p>
<p>But in this post, we will deploy to the local in-memory instance of the Hardhat Network to keep things simple. This network is run on startup by default.</p>
<p>Make a new directory called <code>scripts</code> in the root directory and <code>deploy.js</code> in it.</p>
<pre><code>mkdir scripts &amp;&amp; cd scripts &amp;&amp; touch deploy.js
</code></pre><p>Here is the deploy script. You deploy along with constructor values:</p>
<pre><code class="lang-js"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">main</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> MyCryptoLions = <span class="hljs-keyword">await</span> hre.ethers.getContractFactory(<span class="hljs-string">"MyCryptoLions"</span>);
  <span class="hljs-keyword">const</span> myCryptoLions = <span class="hljs-keyword">await</span> MyCryptoLions.deploy(<span class="hljs-string">"MyCryptoLions"</span>, <span class="hljs-string">"MCL"</span>);

  <span class="hljs-keyword">await</span> myCryptoLions.deployed();

  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"MyCryptoLions deployed to:"</span>, myCryptoLions.address);
}

main()
  .then(<span class="hljs-function">() =&gt;</span> process.exit(<span class="hljs-number">0</span>))
  .catch(<span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> {
    <span class="hljs-built_in">console</span>.error(error);
    process.exit(<span class="hljs-number">1</span>);
  });
</code></pre>
<p>You might want to remove <code>console.log()</code> before you deploy. And then run this deploy script with:</p>
<pre><code>npx hardhat run scripts/deploy.js
MyCryptoLions deployed to: <span class="hljs-number">0x5FbDB2315678afecb367f032d93F642f64180aa3</span>
</code></pre><p>Boom! Now your NFT contract is deployed to the local network. </p>
<p>You can target any network configured in the <code>hardhat.config.js</code> depending on your needs. You can find more about configuration <a target="_blank" href="https://hardhat.org/config/">here</a>.</p>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>Hardhat has some other cool features like helpful stack trace, support for multiple Solidity compiler versions, a robust Mainnet forking, great TypeScript support and contract verification in Etherescan. But that’s for another time!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Make an NFT and Render it on the OpenSea Marketplace ]]>
                </title>
                <description>
                    <![CDATA[ By Patrick Collins In this article, I'll show you how to make an NFT without software engineering skills. Then we will learn how to make unlimited customizable NFTs with Brownie, Python, and Chainlink. And we'll see how to render and sell our creatio... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-make-an-nft-and-render-on-opensea-marketplace/</link>
                <guid isPermaLink="false">66d46089a326133d12440a45</guid>
                
                    <category>
                        <![CDATA[ Art ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Blockchain ]]>
                    </category>
                
                    <category>
                        <![CDATA[ decentralization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ NFT ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Thu, 01 Apr 2021 17:05:57 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/03/Advanced-NFT-Deployment---1-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Patrick Collins</p>
<p>In this article, I'll show you how to make an NFT without software engineering skills. Then we will learn how to make unlimited customizable NFTs with <a target="_blank" href="https://eth-brownie.readthedocs.io/en/stable/">Brownie</a>, <a target="_blank" href="https://www.python.org/">Python</a>, and <a target="_blank" href="https://docs.chain.link/docs">Chainlink</a>. And we'll see how to render and sell our creation on the <a target="_blank" href="https://opensea.io/">OpenSea</a> NFT marketplace. </p>
<p>If you're looking for a tutorial that uses Truffle, JavaScript, and fun medieval characters, check out how to <a target="_blank" href="https://blog.chain.link/build-deploy-and-sell-your-own-dynamic-nft/">Build, Deploy, and Sell your NFT here</a>. </p>
<h2 id="heading-what-is-an-nft">What is an NFT?</h2>
<p><a target="_blank" href="https://eips.ethereum.org/EIPS/eip-721">NFTs</a> (Non-Fungible Tokens) can be summed up with one word: "unique". These are smart contracts deployed on a blockchain that represent something unique. </p>
<h3 id="heading-erc20-vs-erc721">ERC20 vs ERC721</h3>
<p>NFTs are a blockchain token standard similar to the <a target="_blank" href="https://www.investopedia.com/news/what-erc20-and-what-does-it-mean-ethereum/">ERC20</a>, like AAVE, SNX, and LINK (technically a ERC677). ERC20s are "fungible" tokens, which means “replaceable” or “interchangeable.” </p>
<p>For example, your dollar bill is going to be worth $1 no matter what dollar bill you use. The serial number on the dollar bill might be different, but the bills are interchangeable and they’ll be worth $1 no matter what. </p>
<p>NFTs, on the other hand, are "non-fungible", and they follow their own token standard, the <a target="_blank" href="https://eips.ethereum.org/EIPS/eip-721">ERC721.</a> For example, the Mona Lisa is "non-fungible". Even though someone can make a copy of it, there will always only be one Mona Lisa. If the Mona Lisa was created on a blockchain, it would be an NFT. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/03/image-145.png" alt="Make an NFT" width="600" height="400" loading="lazy">
_Original Image from <a target="_blank" href="https://en.wikipedia.org/wiki/Mona_Lisa">Wikipedia</a>_</p>
<h2 id="heading-what-are-nfts-for">What are NFTs for?</h2>
<p>NFTs provide value to creators, artists, game designers and more by having a permanent history of deployment stored on-chain. </p>
<p>You'll always know who created the NFT, who owned the NFT, where it came from, and more, giving them a lot of value over traditional art. In traditional art, it can be tricky to understand what a "fake" is, whereas on-chain the history is easily traceable. </p>
<p>And since smart contracts and NFTs are 100% programmable, NFTs can also have added built-in royalties and any other functionality. Compensating artists has always been an issue, since often times an artist's work is spread around without any attribution. </p>
<p>More and more artists and engineers are jumping on this massive value add, because it's finally a great way for artists to be compensated for their work. And more than just that, NFTs are a fun way to show off your creativity and become a collector in a digital world. </p>
<h3 id="heading-the-value-of-nfts">The Value of NFTs</h3>
<p>NFTs have come a long way, and we keep seeing record breaking NFT sales, like "Everydays: The First 5,000 Days” selling for $69.3 million.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/03/Screen-Shot-2021-03-31-at-9.48.19-AM.png" alt="Make an NFT" width="600" height="400" loading="lazy">
<em>Image from <a target="_blank" href="https://twitter.com/ChristiesInc/status/1361670588608176128">Twitter</a></em></p>
<p>So there is a lot of value here, and it's also a fun, dynamic, and engaging way to create art in the digital world and learn about smart contract creation. So now I'll teach you everything you need to know about making NFTs.</p>
<h2 id="heading-how-to-make-an-nft">How to Make an NFT</h2>
<h3 id="heading-what-we-are-not-going-to-cover">What we are not going to cover</h3>
<p>Now, the easiest way to make an NFT is just to go to a platform like <a target="_blank" href="https://opensea.io/">Opensea</a>, <a target="_blank" href="https://rarible.com/">Rarible</a>, or <a target="_blank" href="https://mintable.app/">Mintible</a> and follow their step-by-step guide to deploying on their platform. </p>
<p>You can 100% take this route, however you could be bound to the platform, and you are shoehorned into the functionality the platform has. You can't achieve the unlimited customization, or really utilize any of the advantages NFTs have. But if you're a beginner software engineer, or not very technical, this is the route for you. </p>
<p>If you're looking to become a stronger software engineer, learn some solidity, and have the power to create something with unlimited creativity, then read on!</p>
<p>If you're new to solidity, don't worry, we will go over the basics there as well. </p>
<h2 id="heading-how-to-make-an-nft-with-unlimited-customization">How to Make an NFT with Unlimited Customization</h2>
<p>I'm going to get you jump started with this <a target="_blank" href="https://github.com/PatrickAlphaC/nft-mix">NFT Brownie Mix</a>. This is a working repo with a lot of boilerplate code. </p>
<h3 id="heading-prerequisites">Prerequisites</h3>
<p>We need a few things installed to get started:</p>
<ul>
<li><a target="_blank" href="https://www.python.org/downloads/">Python</a></li>
<li><a target="_blank" href="https://nodejs.org/en/download/">Nodejs</a> and npm</li>
<li><a target="_blank" href="https://metamask.io/">Metamask</a></li>
</ul>
<p>If you're unfamiliar with Metamask, you can <a target="_blank" href="https://docs.chain.link/docs/install-metamask">follow this tutorial</a> to get it set up. </p>
<h3 id="heading-rinkeby-testnet-eth-and-link">Rinkeby Testnet ETH and LINK</h3>
<p>We will also be working on the Rinkeby Ethereum testnet, so we will be deploying our contracts to a real blockchain, for free! </p>
<p>Testnets are great ways to test how our smart contracts behave in the real world. We need Rinkeby ETH and Rinkeby LINK, which we can get for free from the links to the latest faucets from the <a target="_blank" href="https://docs.chain.link/docs/link-token-contracts#rinkeby">Chainlink documentation</a>. </p>
<p>We will also need to add the rinkeby LINK token to our metamask, which we can do by following the <a target="_blank" href="https://docs.chain.link/docs/acquire-link">acquire LINK documentation</a>. </p>
<p>If you're still confused, <a target="_blank" href="https://www.youtube.com/watch?v=4ZgFijd02Jo">you can following along with this video</a>, just be sure to use Rinkeby instead of Ropsten. </p>
<p>When working with a smart contract platform like Ethereum, we need to pay a little bit of ETH, and when getting data from off-chain, we have to pay a little bit of LINK. This is why we need the testnet LINK and ETH.</p>
<p>Awesome, let's dive in. This is <a target="_blank" href="https://testnets.opensea.io/assets/0x8acb7ca932892eb83e4411b59309d44dddbc4cdf/0">the NFT we are going to deploy to OpenSea.</a></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/03/Screen-Shot-2021-03-31-at-10.58.35-AM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-quickstart">Quickstart</h3>
<pre><code class="lang-bash">git <span class="hljs-built_in">clone</span> https://github.com/PatrickAlphaC/nft-mix
<span class="hljs-built_in">cd</span> nft-mix
</code></pre>
<p>Awesome! Now we need to install the <code>ganache-cli</code> and <code>eth-brownie</code>.</p>
<pre><code>pip install eth-brownie
npm install -g ganache-cli
</code></pre><p>Now we can <a target="_blank" href="https://www.twilio.com/blog/2017/01/how-to-set-environment-variables.html">set our environment variables</a>. If you're unfamiliar with environment variables, you can just add them into your <code>.env</code> file, and then run:</p>
<p><code>source .env</code></p>
<p>A sample <code>.env</code> should be in the repo you just cloned with the environment variables commented out. Uncomment them to use them!</p>
<p>You'll need a <code>WEB3_INFURA_PROJECT_ID</code> and a <code>PRIVATE_KEY</code> . The <code>WEB3_INFURA_PROJECT_ID</code> can be found be signing up for a free <a target="_blank" href="https://infura.io/">Infura</a> account. This will give us a way to send transactions to the blockchain.</p>
<p>We will also need a private key, which you can get from your Metamask. Hit the 3 little dots, and click <code>Account Details</code> and <code>Export Private Key</code>. Please do NOT share this key with anyone if you put real money in it!</p>
<pre><code><span class="hljs-keyword">export</span> PRIVATE_KEY=YOUR_KEY_HERE
<span class="hljs-keyword">export</span> WEB3_INFURA_PROJECT_ID=YOUR_PROJECT_ID_HERE
</code></pre><p>Now we can deploy our NFT contract and create our first collectible with the following two commands. </p>
<pre><code>brownie run scripts/simple_collectible/deploy_simple.py --network rinkeby
brownie run scripts/simple_collectible/create_collectible.py --network rinkeby
</code></pre><p>The first script deploys our NFT contract to the Rinkeby blockchain, and the second one creates our first collectible. </p>
<p>You've just deployed your first smart contract!</p>
<p>It doesn't do much at all, but don't worry – I'll show you how to render it on OpenSea in the advanced part of this tutorial. But first, let's look at the ERC721 token standard. </p>
<h2 id="heading-the-erc721-token-standard">The ERC721 Token Standard</h2>
<p>Let's take a look at the contract that we just deployed, in the <code>SimpleCollectible.sol</code> file. </p>
<pre><code class="lang-javascript"><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>
pragma solidity <span class="hljs-number">0.6</span><span class="hljs-number">.6</span>;

<span class="hljs-keyword">import</span> <span class="hljs-string">"@openzeppelin/contracts/token/ERC721/ERC721.sol"</span>;

contract SimpleCollectible is ERC721 {
    uint256 public tokenCounter;
    <span class="hljs-keyword">constructor</span> () public ERC721 ("Dogie", "DOG"){
        tokenCounter = <span class="hljs-number">0</span>;
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">createCollectible</span>(<span class="hljs-params">string memory tokenURI</span>) <span class="hljs-title">public</span> <span class="hljs-title">returns</span> (<span class="hljs-params">uint256</span>) </span>{
        uint256 newItemId = tokenCounter;
        _safeMint(msg.sender, newItemId);
        _setTokenURI(newItemId, tokenURI);
        tokenCounter = tokenCounter + <span class="hljs-number">1</span>;
        <span class="hljs-keyword">return</span> newItemId;
    }

}
</code></pre>
<p>We are using the <a target="_blank" href="https://github.com/OpenZeppelin/openzeppelin-contracts">OpenZepplin</a> package for the ERC721 token. This package that we've imported allows us to use all the functions of a typical ERC721 token. This defines all the functionality that our tokens are going to have, like <code>transfer</code> which moves tokens to new users, <code>safeMint</code> which creates new tokens, and more. </p>
<p>You can find all the functions that are given to our contract by checking out the <a target="_blank" href="https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/ERC721.sol">OpenZepplin ERC721 token contract</a>. Our contract inherits these functions on this line: </p>
<pre><code>contract SimpleCollectible is ERC721 {
</code></pre><p>This is how solidity does inheritance. When we deploy a contract, the <code>constructor</code> is automatically called, and it takes a few parameters.</p>
<pre><code><span class="hljs-keyword">constructor</span> () public ERC721 ("Dogie", "DOG"){
        tokenCounter = <span class="hljs-number">0</span>;
    }
</code></pre><p>We also use the constructor of the <code>ERC721</code>, in our constructor, and we just have to give it a name and a symbol. In our case, it's "Dogie" and "DOG". This means that every NFT that we create will be of type Dogie/DOG. </p>
<p>This is like how every Pokemon card is still a pokemon, or every baseball player on a trading card is still a baseball player. Each baseball player is unique, but they are still all baseball players. We are just using type <code>DOG</code>. </p>
<p>We have <code>tokenCounter</code> at the top that counts how many NFTs we've created of this type. Each new token gets a <code>tokenId</code> based on the current <code>tokenCounter</code>.</p>
<p>We can actually create an NFT with the <code>createCollectible</code> function. This is what we call in our <code>create_collectible.py</code> script. </p>
<pre><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">createCollectible</span>(<span class="hljs-params">string memory tokenURI</span>) <span class="hljs-title">public</span> <span class="hljs-title">returns</span> (<span class="hljs-params">uint256</span>) </span>{
        uint256 newItemId = tokenCounter;
        _safeMint(msg.sender, newItemId);
        _setTokenURI(newItemId, tokenURI);
        tokenCounter = tokenCounter + <span class="hljs-number">1</span>;
        <span class="hljs-keyword">return</span> newItemId;
    }
</code></pre><p>The <code>_safeMint</code> function creates the new NFT, and assigns it to whoever called <code>createdCollectible</code> , aka the <code>msg.sender</code>, with a <code>newItemId</code> derived from the <code>tokenCounter</code>. This is how we can keep track of who owns what, by checking the owner of the <code>tokenId</code>.</p>
<p>You'll notice that we also call <code>_setTokenURI</code>. Let's talk about that.</p>
<h2 id="heading-what-are-nft-metadata-and-tokenuri">What are NFT Metadata and TokenURI?</h2>
<p>When smart contracts were being created, and NFTs were being created, people quickly realized that it's <em>reaaaally</em> expensive to deploy a lot of data to the blockchain. Images as small as one KB can easily <a target="_blank" href="https://ethereum.stackexchange.com/a/896/57451">cost over $1M to store</a>. </p>
<p>This is clearly an issue for NFTs, since having creative art means you have to store this information somewhere. They also wanted a lightweight way to store attributes about an NFT – and this is where the tokenURI and metadata come into play.</p>
<h3 id="heading-tokenuri">TokenURI</h3>
<p>The <code>tokenURI</code> on an NFT is a unique identifier of what the token "looks" like. A URI could be an API call over HTTPS, an IPFS hash, or <a target="_blank" href="https://danielmiessler.com/study/difference-between-uri-url/">anything else</a> unique. </p>
<p>They follow a standard of showing metadata that looks like this:</p>
<pre><code class="lang-json">{
    <span class="hljs-attr">"name"</span>: <span class="hljs-string">"name"</span>,
    <span class="hljs-attr">"description"</span>: <span class="hljs-string">"description"</span>,
    <span class="hljs-attr">"image"</span>: <span class="hljs-string">"https://ipfs.io/ipfs/QmTgqnhFBMkfT9s8PHKcdXBn1f5bG3Q5hmBaR4U6hoTvb1?filename=Chainlink_Elf.png"</span>,
    <span class="hljs-attr">"attributes"</span>: [
        {
            <span class="hljs-attr">"trait_type"</span>: <span class="hljs-string">"trait"</span>,
            <span class="hljs-attr">"value"</span>: <span class="hljs-number">100</span>
        }
    ]
}
</code></pre>
<p>These show what an NFT looks like, and its attributes. The <code>image</code> section points to another URI of what the NFT looks like. This makes it easy for NFT platforms like Opensea, Rarible, and Mintable to render NFTs on their platforms, since they are all looking for this metadata. </p>
<h3 id="heading-off-chain-metadata-vs-on-chain-metadata">Off-Chain Metadata vs On-Chain Metadata</h3>
<p>Now you might be thinking "wait... if the metadata isn't on-chain, does that mean my NFT might go away at some point"? And you'd be correct. </p>
<p>You'd also be correct in thinking that off-chain metadata means that you can't use that metadata to have your smart contracts interact with each other. </p>
<p>This is why we want to focus on on-chain metadata, so that we can program our NFTs to interact with each other. </p>
<p>We still need the <code>image</code> part of the off-chain metadata, though, since we don't have a great way to store large images on-chain. But don't worry, we can do this for free on a decentralized network still by using <a target="_blank" href="https://ipfs.io/">IPFS</a>. </p>
<p>Here's an example imageURI from IPFS that shows the <a target="_blank" href="https://opensea.io/assets/0x8d78277bc2c63f07efc2c0c8a8512de4ad459a05/1">Chainlink Elf</a> created in the <a target="_blank" href="https://blog.chain.link/build-deploy-and-sell-your-own-dynamic-nft/">Dungeons and Dragons tutorial</a>. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/03/Screen-Shot-2021-03-31-at-12.15.22-PM.png" alt="Make an NFT" width="600" height="400" loading="lazy">
<em>The Chainlink Elf</em></p>
<p>We didn't set a tokenURI for the simple NFT because we wanted to just show a basic example. </p>
<p>Let's jump into the advanced NFT now, so we can see some of the amazing features we can do with on-chain metadata, have the NFT render on opeansea, and get our Dogie up! </p>
<p>If you want a refresher video on the section we just went over, follow along with the <a target="_blank" href="https://www.youtube.com/watch?v=ZH_7nEIJDUY">deploying a simple NFT video.</a> </p>
<h2 id="heading-dynamic-and-advanced-nfts">Dynamic and Advanced NFTs</h2>
<p><a target="_blank" href="https://blog.chain.link/build-deploy-and-sell-your-own-dynamic-nft/">Dynamic NFTs</a> are NFTs that can change over time, or have on-chain features that we can use to interact with each other. These are the NFTs that have the unlimited customization for us to make entire games, worlds, or interactive art of some-kind. Let's jump into the advanced section.</p>
<h3 id="heading-advanced-quickstart">Advanced Quickstart</h3>
<p>Make sure you have enough testnet ETH and LINK in your metamask, then run the following:</p>
<pre><code>brownie run scripts/advanced_collectible/deploy_advanced.py --network rinkeby
brownie run scripts/advanced_collectible/create_collectible.py --network rinkeby
</code></pre><p>Our collectible here is a random dog breed returned from the <a target="_blank" href="https://docs.chain.link/docs/chainlink-vrf">Chainlink VRF</a>. Chainlink VRF is a way to get provable random numbers, and therefore true scarcity in our NFTs. We then want to create its metadata.</p>
<pre><code>brownie run scripts/advanced_collectible/create_metadata.py --network rinkeby
</code></pre><p>We can then optionally upload this data to IPFS so that we can have a tokenURI. I'll show you how to do that later. For now, we are just going to use the sample tokenURI of:</p>
<pre><code>https:<span class="hljs-comment">//ipfs.io/ipfs/Qmd9MCGtdVz2miNumBHDbvj8bigSgTwnr4SbyH6DNnpWdt?filename=1-PUG.json</span>
</code></pre><p>If you download <a target="_blank" href="https://chrome.google.com/webstore/detail/ipfs-companion/nibjojkomfdiaoajekhjakgkdhaomnch?hl=en">IPFS Companion</a> into your browser you can use that URL to see what the URI returns. It'll look like this:</p>
<pre><code class="lang-json">{
    <span class="hljs-attr">"name"</span>: <span class="hljs-string">"PUG"</span>,
    <span class="hljs-attr">"description"</span>: <span class="hljs-string">"An adorable PUG pup!"</span>,
    <span class="hljs-attr">"image"</span>: <span class="hljs-string">"https://ipfs.io/ipfs/QmSsYRx3LpDAb1GZQm7zZ1AuHZjfbPkD6J7s9r41xu1mf8?filename=pug.png"</span>,
    <span class="hljs-attr">"attributes"</span>: [
        {
            <span class="hljs-attr">"trait_type"</span>: <span class="hljs-string">"cuteness"</span>,
            <span class="hljs-attr">"value"</span>: <span class="hljs-number">100</span>
        }
    ]
}
</code></pre>
<p>Then we can run our <code>set_tokenuri.py</code> script:</p>
<pre><code>brownie run scripts/advanced_collectible/set_tokenuri.py --network rinkeby
</code></pre><p>And we will get an output like this: </p>
<pre><code>Running <span class="hljs-string">'scripts/advanced_collectible/set_tokenuri.py::main'</span>...
Working on rinkeby
Transaction sent: <span class="hljs-number">0x8a83a446c306d6255952880c0ca35fa420248a84ba7484c3798d8bbad421f88e</span>
  Gas price: <span class="hljs-number">1.0</span> gwei   Gas limit: <span class="hljs-number">44601</span>   Nonce: <span class="hljs-number">354</span>
  AdvancedCollectible.setTokenURI confirmed - Block: <span class="hljs-number">8331653</span>   Gas used: <span class="hljs-number">40547</span> (<span class="hljs-number">90.91</span>%)

Awesome! You can view your NFT at https:<span class="hljs-comment">//testnets.opensea.io/assets/0x679c5f9adC630663a6e63Fa27153B215fe021b34/0</span>
Please give up to <span class="hljs-number">20</span> minutes, and hit the <span class="hljs-string">"refresh metadata"</span> button
</code></pre><p>And we can hit the link given to see what it looks like on Opensea! You may have to hit the <code>refresh metadata</code> button and wait a few minutes.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/03/Screen-Shot-2021-03-31-at-12.33.42-PM.png" alt="Make an NFT" width="600" height="400" loading="lazy">
<em>Refresh Metadata</em></p>
<h2 id="heading-the-random-breed">The Random Breed</h2>
<p>Let's talk about what we just did. Here is our <code>AdvancedCollectible.sol</code>:</p>
<pre><code>pragma solidity <span class="hljs-number">0.6</span><span class="hljs-number">.6</span>;

<span class="hljs-keyword">import</span> <span class="hljs-string">"@openzeppelin/contracts/token/ERC721/ERC721.sol"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"@chainlink/contracts/src/v0.6/VRFConsumerBase.sol"</span>;

contract AdvancedCollectible is ERC721, VRFConsumerBase {
    uint256 public tokenCounter;
    enum Breed{PUG, SHIBA_INU, BRENARD}
    <span class="hljs-comment">// add other things</span>
    mapping(<span class="hljs-function"><span class="hljs-params">bytes32</span> =&gt;</span> address) public requestIdToSender;
    mapping(<span class="hljs-function"><span class="hljs-params">bytes32</span> =&gt;</span> string) public requestIdToTokenURI;
    mapping(<span class="hljs-function"><span class="hljs-params">uint256</span> =&gt;</span> Breed) public tokenIdToBreed;
    mapping(<span class="hljs-function"><span class="hljs-params">bytes32</span> =&gt;</span> uint256) public requestIdToTokenId;
    event requestedCollectible(bytes32 indexed requestId); 


    bytes32 internal keyHash;
    uint256 internal fee;
    uint256 public randomResult;
    <span class="hljs-keyword">constructor</span>(address _VRFCoordinator, address _LinkToken, bytes32 _keyhash)
    public 
    VRFConsumerBase(_VRFCoordinator, _LinkToken)
    ERC721("Dogie", "DOG")
    {
        tokenCounter = <span class="hljs-number">0</span>;
        keyHash = _keyhash;
        fee = <span class="hljs-number">0.1</span> * <span class="hljs-number">10</span> ** <span class="hljs-number">18</span>;
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">createCollectible</span>(<span class="hljs-params">string memory tokenURI, uint256 userProvidedSeed</span>) 
        <span class="hljs-title">public</span> <span class="hljs-title">returns</span> (<span class="hljs-params">bytes32</span>)</span>{
            bytes32 requestId = requestRandomness(keyHash, fee, userProvidedSeed);
            requestIdToSender[requestId] = msg.sender;
            requestIdToTokenURI[requestId] = tokenURI;
            emit requestedCollectible(requestId);
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fulfillRandomness</span>(<span class="hljs-params">bytes32 requestId, uint256 randomNumber</span>) <span class="hljs-title">internal</span> <span class="hljs-title">override</span> </span>{
        address dogOwner = requestIdToSender[requestId];
        string memory tokenURI = requestIdToTokenURI[requestId];
        uint256 newItemId = tokenCounter;
        _safeMint(dogOwner, newItemId);
        _setTokenURI(newItemId, tokenURI);
        Breed breed = Breed(randomNumber % <span class="hljs-number">3</span>); 
        tokenIdToBreed[newItemId] = breed;
        requestIdToTokenId[requestId] = newItemId;
        tokenCounter = tokenCounter + <span class="hljs-number">1</span>;
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">setTokenURI</span>(<span class="hljs-params">uint256 tokenId, string memory _tokenURI</span>) <span class="hljs-title">public</span> </span>{
        <span class="hljs-built_in">require</span>(
            _isApprovedOrOwner(_msgSender(), tokenId),
            <span class="hljs-string">"ERC721: transfer caller is not owner nor approved"</span>
        );
        _setTokenURI(tokenId, _tokenURI);
    }
}
</code></pre><p>We use the Chainlink VRF to create a random breed from a list of <code>PUG, SHIBA_INU, BRENARD</code>. When we call <code>createCollectible</code> this time, we actually kicked off a request to the Chainlink VRF node off-chain, and returned with a random number to create the NFT with one of those 3 breeds. </p>
<p>Using true randomness in your NFTs is a great way to create true scarcity, and using an Chainlink oracle random number means that your number is provably random, and can't be influenced by the miners. </p>
<p>You can learn more about <a target="_blank" href="https://docs.chain.link/docs/chainlink-vrf">Chainlink VRF in the documentation</a>. </p>
<p>The Chainlink node responds by calling the <code>fulfillRandomness</code> function, and creates the collectible based on the random number. We then still have to call <code>_setTokenURI</code> to give our NFT the appearance that it needs. </p>
<p>We didn't give our NFT attributes here, but attributes are a great way to have our NFTs battle and interact. You can see a great example of NFTs with attributes in this <a target="_blank" href="https://github.com/PatrickAlphaC/dungeons-and-dragons-nft">Dungeons and Dragons example</a>. </p>
<h3 id="heading-metadata-from-ipfs">Metadata from IPFS</h3>
<p>We are using IPFS to store two files:</p>
<ol>
<li>The image of the NFT (the pug image)</li>
<li>The tokenURI file (the JSON file which also includes the link of the image)</li>
</ol>
<p>We use IPFS because it's a free decentralized platform. We can add our tokenURIs and images to IPFS by downloading <a target="_blank" href="https://docs.ipfs.io/install/ipfs-desktop/">IPFS desktop</a>, and hitting the <code>import</code> button. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/03/Screen-Shot-2021-03-31-at-12.43.13-PM.png" alt="Make an NFT" width="600" height="400" loading="lazy">
<em>IPFS add a file</em></p>
<p>Then, we can share the URI by hitting the 3 dots next to the file we want to share, hitting <code>share link</code> and copying the link given. We can then add this link into our <code>set_tokenuri.py</code> file to change the token URI that we want to use. </p>
<h3 id="heading-persistance">Persistance</h3>
<p>However, if the tokenURI is only on our node, this means when our node is down, no one else can view it. So we want others to <code>pin</code> our NFT. We can use a pinning service like <a target="_blank" href="https://pinata.cloud/">Pinata</a> to help keep our data alive even when our IPFS node is down.</p>
<p>I imagine in the future more and more metadata will be stored on IPFS and decentralized storage platforms. Centralized servers can go down, and would mean that the art on those NFTs is lost forever. Be sure to check where the tokenURI of the NFT you use is located! </p>
<p>I also expect down the line that more people will use dStorage platforms like <a target="_blank" href="https://docs.filecoin.io/">Filecoin</a>, as using a pinning service also isn't as decentralized as it should be.</p>
<h2 id="heading-going-forward">Going forward</h2>
<p>If you'd like a video walkthrough of the advanced NFT, you can watch the <a target="_blank" href="https://www.youtube.com/watch?v=tCR7b9p9GiM">advanced NFT video</a>. </p>
<p>Now you have the skills to make beautiful fun, customizable, interactive NFTs, and have them render on a marketplace. </p>
<p>NFTs are fun, powerful ways to have artists accurately compensated for all the hard work that they do. Good luck, and remember to have fun!</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
