<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Archie Smyth</title>
    <description>The latest articles on DEV Community by Archie Smyth (@yournewempire).</description>
    <link>https://dev.to/yournewempire</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F597660%2F0334991f-76b2-4c72-b5ae-b642acf6214d.png</url>
      <title>DEV Community: Archie Smyth</title>
      <link>https://dev.to/yournewempire</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/yournewempire"/>
    <language>en</language>
    <item>
      <title>Deploying Regenerative NFTs on Polygon</title>
      <dc:creator>Archie Smyth</dc:creator>
      <pubDate>Sun, 14 Nov 2021 16:32:17 +0000</pubDate>
      <link>https://dev.to/yournewempire/deploying-regenerative-nfts-on-polygon-5c7p</link>
      <guid>https://dev.to/yournewempire/deploying-regenerative-nfts-on-polygon-5c7p</guid>
      <description>&lt;p&gt;In my &lt;a href="https://dev.to/yournewempire/deploy-nfts-with-truffle-ipfs-opensea-polygon-5581"&gt;previous blog post&lt;/a&gt;, I put together a truffle project that could deploy ERC-721 token contracts to Polygon's Mumbai test network for compatibility for OpenSea. Today, I am ready to improve on this and show you devs and artists a couple of repositories that will help when deploying NFTs. Since my first post, I have been talking to a client about the power of regenerative art. Where artists can save time designing thousands of NFTs. I did some digging, and with some help from &lt;a href="https://www.youtube.com/watch?v=VglTdr0n5ZQ" rel="noopener noreferrer"&gt;Moralis YT&lt;/a&gt; and &lt;a href="https://github.com/HashLips/hashlips_art_engine" rel="noopener noreferrer"&gt;HashLips GitHub&lt;/a&gt;, I conjured up a couple repos. Unfortunately, I have not configured an ERC-1155 example yet, but it is not too dissimilar from this code. So let's see what improvements I have made from the previous ERC-721 boilerplate.&lt;/p&gt;

&lt;h3&gt;
  
  
  The improvements
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Migration from Truffle to Hardhat.&lt;/li&gt;
&lt;li&gt;All of the benefits that come with Hardhat. Including straight-forward contract testing, more frequent updates, a larger community and much more.&lt;/li&gt;
&lt;li&gt;Enabled Meta-transactions to allow gas-less transactions when assets are bought on OpenSea.&lt;/li&gt;
&lt;li&gt;In addition to the Hardhat environment, I have also added a fork of &lt;a href="https://github.com/HashLips" rel="noopener noreferrer"&gt;HashLips&lt;/a&gt; to generate art metadata (purely optional)&lt;/li&gt;
&lt;li&gt;The HashLips art engine fork includes code for uploading NFT metadata to IPFS via a Moralis endpoint&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Repos: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/YourNewEmpire/hashlips_art_engine" rel="noopener noreferrer"&gt;Forked HashLips art engine for IPFS uploads&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/YourNewEmpire/Hardhat-OpenSea-ERC721" rel="noopener noreferrer"&gt;Hardhat ERC-721&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;My Working Example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://opensea.io/collection/arch-regen-nfts" rel="noopener noreferrer"&gt;OpenSea&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://polygonscan.com/address/0xe659d2a4d136d3f12c815304fa928fdaa43c17ba" rel="noopener noreferrer"&gt;PolygonScan&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;You will need funds on Polygon mainnet/testnet if you are to deploy any contracts&lt;/strong&gt; (I have used mainnet to test meta tx's)&lt;/p&gt;

&lt;p&gt;Firstly, I will show you the HashLips art engine fork to generate and upload NFTs. Lastly, I go through the Hardhat setup for deploying the contracts to Polygon.&lt;/p&gt;

&lt;h2&gt;
  
  
  HashLips art engine
&lt;/h2&gt;

&lt;p&gt;To get started clone the HashLips fork. If you want to deploy contracts too, then get both. They have readme files that you can follow as well:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/YourNewEmpire/hashlips_art_engine" rel="noopener noreferrer"&gt;Forked HashLips art engine for IPFS uploads&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/YourNewEmpire/Hardhat-OpenSea-ERC721" rel="noopener noreferrer"&gt;Hardhat ERC-721&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Moralis IPFS setup
&lt;/h3&gt;

&lt;p&gt;You will need to an account at &lt;a href="https://www.moralis.io" rel="noopener noreferrer"&gt;Moralis&lt;/a&gt; to get an API key. Then you may send your metadata in POST requests to &lt;a href="https://deep-index.moralis.io/api/v2/ipfs/uploadFolder" rel="noopener noreferrer"&gt;https://deep-index.moralis.io/api/v2/ipfs/uploadFolder&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Once logged in, find the WEB3 API in the sidebar and copy the api key:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FYourNewEmpire%2Fhashlips_art_engine%2Fraw%2Fmain%2Fcommon%2Fmoralisweb3api.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FYourNewEmpire%2Fhashlips_art_engine%2Fraw%2Fmain%2Fcommon%2Fmoralisweb3api.png" alt="copymoralisweb3key"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Paste it into new .env file for &lt;code&gt;MORALIS&lt;/code&gt;. &lt;/p&gt;
&lt;h3&gt;
  
  
  OpenSea Collection Metadata
&lt;/h3&gt;

&lt;p&gt;If you want to test OpenSea Collection metadata, then replace (or use) the image and json files in &lt;code&gt;moralisIPFS/collection#1&lt;/code&gt; and use the names I have used to keep the scripts working. You can edit &lt;code&gt;scripts/collectionImage.js&lt;/code&gt; or &lt;code&gt;scripts/collectionJson.js&lt;/code&gt; to read the collection metadata on lines 15 or 17.&lt;/p&gt;

&lt;p&gt;Then, run &lt;code&gt;node moralisIPFS/scripts/collectionImage.js&lt;/code&gt; in the console. If no error occurred, then copy your uri link from the console log. Mine looks like this:&lt;br&gt;
&lt;code&gt;{path:'https://ipfs.moralis.io:2053/ipfs/Qmbd46WBvCK33kuGcEb7LtQkWcXW3ygDEgBv5rdFvnJ7RX/collection-1/image.gif'}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You can change how your deployed IPFS url trails in the &lt;code&gt;collectionImage.js&lt;/code&gt; at line 18.&lt;/p&gt;

&lt;p&gt;You will need this link in your &lt;code&gt;collectionJson.js&lt;/code&gt; scripts to complete the collection metadata. If you look in the json script at line 25, you can see the format of IPFS image link:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
                  path: `collection-1/collection.json`,
                  content: {
                        ...parsed,
                        //! here
                        image: `ipfs://Qmbd46WBvCK33kuGcEb7LtQkWcXW3ygDEgBv5rdFvnJ7RX/collection-1/image.gif`
                  }
            }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So copy your link from the hash trail and up and swap mine for it: Qmbd46WBvCK33kuGcEb7LtQkWcXW3ygDEgBv5rdFvnJ7RX/collection-1/image.gif&lt;/p&gt;

&lt;p&gt;Now you can run &lt;code&gt;node moralisIPFS/scripts/collectionJson.js&lt;/code&gt; to finalise your collection metadata. Copy the json uri link from the console and, open &lt;code&gt;GameItem.sol&lt;/code&gt; in your Hardhat project. Paste it here at line 232 after '/ipfs/':&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  function contractURI() public pure returns (string memory) {
        return "https://ipfs.io/ipfs/yourhash/path/to/file.json";
    }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  NFT Metadata
&lt;/h3&gt;

&lt;p&gt;Before generating your art, be sure to check &lt;code&gt;moralisIPFS/scripts/numOfItems.js&lt;/code&gt;. This is a variable for the upload scripts that we need to run shortly. &lt;/p&gt;

&lt;p&gt;If you look in the project folder you can see the &lt;strong&gt;layers&lt;/strong&gt; folder. Each folder in the layers folder is each layer/piece in the final output. When you inspect the layers folder further, you notice that each layer folder will need multiple variations of that layer, to have more combinations of NFTs. For editing the rarity, you can change the '#1-99' on each layer file for the percentage chance of it appearing in outputs. However, I shall be using the helpful boilerplate from HashLips.&lt;/p&gt;

&lt;p&gt;If you navigate to the src/config.js file, you can see theres a few bits to configure here. One is the &lt;code&gt;layersConfigurations&lt;/code&gt; variable. Here you can set the number NFTs outputted, and the order of the layers that are placed in the image. I only minted 5 but, with the boilerplate layers you can make up to 15 or more. &lt;/p&gt;

&lt;p&gt;Now, onto the NFTs. After running &lt;code&gt;node index.js&lt;/code&gt; the NFTs will be generated and you can see the console logs to confirm. These json/image outputs can be found in the &lt;code&gt;moralisIPFS/build&lt;/code&gt; folder.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before going any further&lt;/strong&gt;: Ensure to edit my &lt;code&gt;moralisIPFS/scripts/numOfItems.js&lt;/code&gt; to match the number of editions you have set in the HashLips config. This number will be read by the upload scripts to upload the correct amount.&lt;/p&gt;

&lt;p&gt;You can now run &lt;code&gt;node moralisIPFS/scripts/images721.js&lt;/code&gt;. If successful, this will upload the files and log your image IPFS links. You will need the long hash from one of those image links:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[
  {
    path: 'https://ipfs.moralis.io:2053/ipfs/QmVgGeRfv1e4EMi6a4A7UEAAcZuESiNQbGBeX7kJaNLYKy/images/1.png'
  }
],
[
  {
    path: 'https://ipfs.moralis.io:2053/ipfs/QmVgGeRfv1e4EMi6a4A7UEAAcZuESiNQbGBeX7kJaNLYKy/images/2.png'
  }
]

//and so on
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just as you did with the collection metadata, you will paste the IPFS hash from the upload logs into your &lt;code&gt;metadata721.js&lt;/code&gt; script at line 23, replacing my dummy hash like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    path: `metadata/${i}.json`,
    content: {
        ...parsed,
        image: `ipfs://PASTE-YOUR-HASH-HERE/images/${i}.png`
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This metadata script will read the JSONs generated by HashLips, but replaces the image value to what you see above. So, now you have your metadata script ready, you should run &lt;code&gt;node moralisIPFS/scripts/metadata721.js&lt;/code&gt; to upload the metadata to IPFS. Copy full uri from the console log, open your Hardhat project, and navigate to &lt;code&gt;scripts/mint.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for (var i = 1; i &amp;lt;= NUM_ITEMS; i++) {
            await gameItem.mintItem(OWNER_ADDRESS,`your-metadata-uri`);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Paste the uri in to the mintItem function parameters to match the following format:&lt;br&gt;
&lt;code&gt;https://ipfs.io/ipfs/bafybeickmuro374jjqidtotrxhvqubfdwpby3sm4k4ydurv4c3h4l4buni/metadata/${i}.json&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;With that done, our NFT metadata is ready and we can deploy and mint the NFTs.&lt;/p&gt;
&lt;h2&gt;
  
  
  Hardhat Contracts
&lt;/h2&gt;

&lt;p&gt;For a quick start, you can check the readme file. In detail, you will need to run &lt;code&gt;npm i&lt;/code&gt; and add a &lt;code&gt;.env&lt;/code&gt; file with the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MNEMONIC=privatekey. not the seedphrase
MATIC_APP_ID=appid_from_maticvigil
POLYGONSCAN=apikey_from_polygonscan
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need the POLYGONSCAN var when running &lt;code&gt;npx hardhat verify&lt;/code&gt; to verify contracts on polygonscan. This part is &lt;strong&gt;optional&lt;/strong&gt; but recommended if you need your source code verified.&lt;/p&gt;

&lt;p&gt;You can set your own name and ticker in the &lt;code&gt;scripts/deploy.js&lt;/code&gt; file, if you need a specific name and ticker.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before minting, be sure to find NUM_ITEMS in scripts/mint.js and set it to the number of JSONs you deployed.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After successfully running &lt;code&gt;npx hardhat run --network matic scripts/deploy.js&lt;/code&gt;, the console will log your contract address. Copy that, and paste it into line 8 contract.attach function in &lt;code&gt;mint.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;mint.js&lt;/code&gt; you will see an OWNER_ADDRESS variable. Paste your deployer account address in there for the mintItem function to execute and mint to yourself. &lt;/p&gt;

&lt;p&gt;Now that your minting script is ready, you can run that with &lt;code&gt;npx hardhat run --network matic scripts/mint.js&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;And thats it. Now you should check PolygonScan and OpenSea for your .&lt;/p&gt;

&lt;h2&gt;
  
  
  Final notes
&lt;/h2&gt;

&lt;p&gt;So there you go. You can now deploy ERC-721 regenerative NFTs for OpenSea on Polygon/Matic. With help from Filip at Moralis, I was able to add bulk IPFS uploads. The setup is still a bit cumbersome, because you are still required to do the images first then copy the uri for the json scripts.&lt;/p&gt;

&lt;h3&gt;
  
  
  Possible Improvements
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Automate the scripts so that the dev does less copying and hard-coding.&lt;/li&gt;
&lt;li&gt;Fill in the hardhat.config.js for other networks.&lt;/li&gt;
&lt;li&gt;Add external/proxy contracts for more flexibilty and upgradeability.&lt;/li&gt;
&lt;li&gt;Move the HashLips project into the Hardhat project for 1 repo.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Any more improvements? Go ahead and suggest them! &lt;/p&gt;

&lt;p&gt;You can find my working example &lt;a href="https://opensea.io/collection/arch-regen-nfts" rel="noopener noreferrer"&gt;here on OpenSea&lt;/a&gt; and &lt;a href="https://polygonscan.com/address/0xe659d2a4d136d3f12c815304fa928fdaa43c17ba" rel="noopener noreferrer"&gt;here on PolygonScan&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Check these out:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/HashLips" rel="noopener noreferrer"&gt;HashLips&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://admin.moralis.io/register" rel="noopener noreferrer"&gt;Sign up at Moralis&lt;/a&gt; + &lt;a href="//docs.moralis.io"&gt;Docs&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hope you learn't something new and enjoyed it. I am looking forward to seeing success &amp;amp; errors :D.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>ethereum</category>
      <category>solidity</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Deploy NFTs with Truffle, IPFS OpenSea &amp; Polygon</title>
      <dc:creator>Archie Smyth</dc:creator>
      <pubDate>Sun, 12 Sep 2021 13:38:23 +0000</pubDate>
      <link>https://dev.to/yournewempire/deploy-nfts-with-truffle-ipfs-opensea-polygon-5581</link>
      <guid>https://dev.to/yournewempire/deploy-nfts-with-truffle-ipfs-opensea-polygon-5581</guid>
      <description>&lt;h2&gt;
  
  
  Intro to me. My first post
&lt;/h2&gt;

&lt;p&gt;Hello, I have been learning Information Technology all my life (21 now), it's my &lt;em&gt;profession&lt;/em&gt;. For the past 18 months, studying JS and Solidity has been ideal. Considering the position I was in, which was 2 years of messing with industries I had no interest in, programming has helped me hugely with my adult life. It has provided me meaning and something to structure my life with/around, and taught me to organise my life. I was confused after leaving college in 2018, finishing my course in IT, but having no clue of where I was going to be. As I was growing up, I was scared of anything more than simple, like programming. I was not &lt;strong&gt;curious&lt;/strong&gt; to learn anything and would be anxious of what others thought of me when I succeeded/failed. Slowly, I came out of this hole. This required me to be more self-aware. I learn't my skills, starting in small baby steps (helloWorld.js, print to console and all that :D.) which is definitely the way to go. Patience was key. With experience in React.js and Express.js, as well as Solidity, I am aiming for a career as a full-stack blockchain app dev. &lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://github.com/YourNewEmpire/Truffle-Tutorial-ERC721"&gt;The OLD GitHub Repo&lt;/a&gt;
&lt;/h2&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://github.com/YourNewEmpire/Hardhat-Opensea-ERC721"&gt;The New Hardhat repo with MetaTXs on Polygon&lt;/a&gt;
&lt;/h2&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://github.com/YourNew%20on%20Polygon%20Empire/Hardhat-Opensea-Boilerplate"&gt;A New Hardhat repo with MetaTXs and ERC1155 support&lt;/a&gt;
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Here you will learn the basics of deploying a simple ERC-721 contract to the &lt;a href="https://mumbai.polygonscan.com/"&gt;Mumbai&lt;/a&gt; testnet and how it all works.
&lt;/h2&gt;

&lt;p&gt;Feel free to skip through the guide, taking only what you need and moving on. However, this is not a 'do this, then do this' tutorial (or whatever the slang is for that). I want to explain what is going on in the code, creating some knowledge for you, albeit with basic tools. Prepare for this to get verbose.&lt;/p&gt;

&lt;p&gt;This is inspired by the &lt;a href="https://docs.opensea.io/docs/developer-tutorials"&gt;ERC-721 Opensea Tutorial&lt;/a&gt;, as well as the &lt;a href="https://docs.openzeppelin.com/contracts/4.x/erc721"&gt;Openzeppelin ERC-721 Tutorial&lt;/a&gt;. I plan on building my own tutorial with additional detail, and smoother guidance. You could just delegate the deploying and minting to Opensea with their frontend, but this is a basic start for developers to build project ideas off of.&lt;/p&gt;

&lt;p&gt;I have found that the following are great for delving into Solidity: &lt;a href="https://cryptodevhub.io/wiki/"&gt;CryptoDevHub&lt;/a&gt; for direction and &lt;a href="https://solidity-by-example.org/"&gt;Solidity By Example&lt;/a&gt; for code examples.&lt;/p&gt;

&lt;p&gt;This project uses the &lt;a href="https://www.trufflesuite.com/docs/truffle/overview"&gt;Truffle&lt;/a&gt; dev framework, as it is easy to begin with, and will give you experience with a node.js environment. Hardhat is preferred in the community. However, my knowledge of hardhat isn't up to standard at this moment. For the scope of this tutorial, Truffle will do nicely, but a Hardhat tutorial is due in the future. If you have 0 knowledge in solidity, you can always check out &lt;a href="//remix.ethereum.org"&gt;Remix&lt;/a&gt; for a quicker, smaller dev tool in the browser to get pracitising the basics of solidity.&lt;/p&gt;

&lt;p&gt;My next tutorial will be focused on &lt;a href="https://docs.openzeppelin.com/contracts/4.x/erc1155"&gt;ERC-1155&lt;/a&gt;, the improvement on ERC-721. This newer standard allows the developer to have multiple collections of fungible and non-fungible tokens in 1 contract, reducing gas.&lt;/p&gt;

&lt;h2&gt;
  
  
  Token Metadata Storage
&lt;/h2&gt;

&lt;p&gt;I will be using Pinata for fast, simple uploads to IPFS. This is a third-party service. Although, In future, I would recommend grabbing &lt;a href="https://docs.ipfs.io/"&gt;IPFS for desktop&lt;/a&gt; so that you can run a node on a Raspberry pi or such. At the time of writing this, the performance of the IPFS network has been fluctuating. Hosting an IPFS node would be the super professional way, but out of the scope of this tutorial. You may be interested in an alternative like &lt;a href="https://www.arweave.org/"&gt;Arweave&lt;/a&gt;. Arweave is similar to IPFS in that its a distributed network. However, Arweave use a &lt;em&gt;&lt;a href="https://www.arweave.org/technology"&gt;Blockweave&lt;/a&gt;&lt;/em&gt; approach, more similar to a chain. Basically, you can pay gas to store immutable files.&lt;/p&gt;

&lt;p&gt;Let us go through some prerequisites that you will need, and links to learn more about the tools you will be using. Previous coding knowledge is a big bonus. I am using &lt;strong&gt;Windows 10&lt;/strong&gt; with default cmd, not ps, but MACos and most Linux distros should function the same for this tutorial. &lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Basic/intermediate knowledge of the Ethereum blockchain (from an app developer view)&lt;/li&gt;
&lt;li&gt;Basics of Solidity, the most popular language for ethereum contracts. This includes the trusted ERC interfaces for contracts to extend, provided by &lt;a href="https://docs.openzeppelin.com/openzeppelin/"&gt;OpenZeppelin&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Node JS installed on your OS. Intermediate knowledge of JavaScript, node.js in particular.&lt;/li&gt;
&lt;li&gt;Truffle CLI installed on your OS. Basics of Truffle dev tool&lt;/li&gt;
&lt;li&gt;Basics of IPFS&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VS Code&lt;/strong&gt; or another text editor IDE like atom , sublime text or eclipse&lt;/li&gt;
&lt;li&gt;MetaMask browser extension, with Polygon Mumbai testnet configured. You can make a new wallet when installing it on another/new browser, to avoid using your main.&lt;/li&gt;
&lt;li&gt;Git CLI for cloning the repo.&lt;/li&gt;
&lt;li&gt;Create an account at &lt;a href="https://www.pinata.cloud/"&gt;Pinata&lt;/a&gt; for 1gb of metadata storage. &lt;/li&gt;
&lt;li&gt;Create an account at &lt;a href="https://rpc.maticvigil.com/"&gt;MaticVigil&lt;/a&gt; for a polygon (&lt;em&gt;fka matic&lt;/em&gt;) node url. Easiest third-party polygon node.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://ethereum.org/en/developers/docs/"&gt;Eth docs for devs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.soliditylang.org/en/v0.8.0/"&gt;Solidity&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.openzeppelin.com/contracts/4.x/erc721"&gt;OpenZeppelin's ERC-721 docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript"&gt;JS docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nodejs.org/en/"&gt;Node.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.trufflesuite.com/docs/truffle/overview"&gt;Truffle docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="//docs.ipfs.io"&gt;IPFS docs&lt;/a&gt; + &lt;a href="https://www.pinata.cloud/"&gt;Pinata&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://code.visualstudio.com/"&gt;VS code dl&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://metamask.io/download"&gt;Metamask&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.matic.network/docs/develop/network-details/network"&gt;Configure matic networks on Metamask&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://git-scm.com/"&gt;Git&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you dont have all of these, or none, I would start by installing Node and then the rest (Truffle framework uses node.js and requires node to install it). Once you have node, you can enter &lt;code&gt;npm i -g truffle&lt;/code&gt; in a fresh terminal.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup Environment
&lt;/h2&gt;

&lt;p&gt;You could start entering &lt;code&gt;git&lt;/code&gt; into the console. Then, check &lt;code&gt;node&lt;/code&gt; as well. With that, boot VS Code, make a new workspace or folder. Open a new terminal in the folder and clone &lt;a href="https://github.com/YourNewEmpire/Truffle-Tutorial-ERC721"&gt;The Repo&lt;/a&gt; with &lt;code&gt;git clone https://github.com/YourNewEmpire/Truffle-Tutorial-ERC721&lt;/code&gt;. Once its cloned, enter &lt;code&gt;npm install&lt;/code&gt; to install all the modules we need for this project, rudimentary npm at work here.&lt;/p&gt;

&lt;p&gt;Create the file '.env' in the roof the project. This file will hold your wallet seed phrase/mnemonic and free matic node url for your scripts. Write the following lines in the file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MNEMONIC=
NODE_KEY=
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Wallet
&lt;/h2&gt;

&lt;p&gt;To begin, lets configure metamask to connect with the mumbai testnet. &lt;a href="https://docs.matic.network/docs/develop/network-details/network"&gt;Go here&lt;/a&gt; to find the network details of matic/mumbai. Select the Mumbai Testnet and copy name, chainid, any 1 of the rpc urls, MATIC as the currency. Type them into your metamask here&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frncz8yrzxlznp2u1biwb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frncz8yrzxlznp2u1biwb.png" alt="metamasknetworks" width="362" height="601"&gt;&lt;/a&gt;&lt;br&gt;
This can be cumbersome, as metamask will close when you interact with the site again. It can be easier to type them in manually. &lt;/p&gt;

&lt;p&gt;Lets get your wallet seed phrase for the environment variables so we can send transactions. Click your avatar in the top right, then settings.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnk8jsm7cw3tzjo9cuzpq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnk8jsm7cw3tzjo9cuzpq.png" alt="metamask1" width="356" height="596"&gt;&lt;/a&gt;&lt;br&gt;
Scroll to find Security &amp;amp; Privacy. Then click the red Reveal Seed button, with your password ready.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1pwzitvwx9fax2qprox3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1pwzitvwx9fax2qprox3.png" alt="metamaskprivatekey" width="358" height="602"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Copy the seed phrase, paste it into your .env, &lt;code&gt;MNEMONIC=private key here&lt;/code&gt;. &lt;strong&gt;Now you can use this var in your deploying and minting scripts&lt;/strong&gt;. They are already binded in the JS scripts using &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals"&gt;Template Literals&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;You will need your eth address for the web3 scripts when minting items to yourself. Copy your address from here&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feiuazj5ugco5oxtni48c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feiuazj5ugco5oxtni48c.png" alt="metamaskaddress" width="363" height="606"&gt;&lt;/a&gt;&lt;br&gt;
Go to &lt;code&gt;truffle-tutorial\scripts\mint.js&lt;/code&gt; in your project. Finally, paste your address into line 14 &lt;code&gt;const OWNER_ADDRESS = "HERE with the string quotes"&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Head over to &lt;a href="https://faucet.matic.network"&gt;Matic Faucet&lt;/a&gt;, &lt;/p&gt;
&lt;h2&gt;
  
  
  Matic/Mumbai node url.
&lt;/h2&gt;

&lt;p&gt;Creating an account at &lt;a href="https://rpc.maticvigil.com/"&gt;MaticVigil&lt;/a&gt; will give you a dedicated rpc url key for smooth contract interactions.&lt;/p&gt;

&lt;p&gt;Once logged in and on the Dashboard, you can Create a new app, this should appear straight away on your Dashboard. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foxryvhl5nb6t13jnvaqu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foxryvhl5nb6t13jnvaqu.png" alt="maticvigildashboard" width="800" height="279"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Copy the App Id:&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz3sxldswfpj2i9e6cly5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz3sxldswfpj2i9e6cly5.png" alt="maticvigilapps" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Paste it into your .env &lt;code&gt;NODE_URL=key&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Ok. With your environment setup, let's move on to getting token metadata ready for when tokens are minted &lt;/p&gt;
&lt;h2&gt;
  
  
  Metadata format for Opensea
&lt;/h2&gt;

&lt;p&gt;To begin here, let's look at minting NFTs at the contract level.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    function mintItem(address player, string memory tokenURI)
        public
        onlyOwner
        returns (uint256)
    {
        _tokenIds.increment();
        uint256 newItemId = _tokenIds.current();
        _mint(player, newItemId);
        _setTokenURI(newItemId, tokenURI);
        return newItemId;
    }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The mint function takes 2 arguments. The important one is the tokenURI. The mintItem function calls the &lt;code&gt;_setTokenURI&lt;/code&gt; function, which takes in the id (index), which was just assigned and the &lt;a href="https://whatis.techtarget.com/definition/URI-Uniform-Resource-Identifier"&gt;URI&lt;/a&gt;. The URI is just a link to the token resource. In our case, it's on IPFS.&lt;/p&gt;

&lt;p&gt;The point here is that Opensea will be querying that tokenURI through the method &lt;code&gt;tokenURI&lt;/code&gt;, part of the ERC-721 standard interface.&lt;/p&gt;

&lt;p&gt;You could also set a baseURI, as mentioned &lt;a href="https://docs.openzeppelin.com/contracts/3.x/api/token/erc721#ERC721-baseURI--"&gt;here&lt;/a&gt;  in the OZ docs. This will be the prefix for token URIs, so that when you mint or query an NFT, you can just pass the id, and the prefix does the rest of the URI format.&lt;/p&gt;

&lt;p&gt;So how does Opensea deal with a resource once it's got a URI to fetch? Here is where Opensea's &lt;a href="https://docs.opensea.io/docs/metadata-standards#metadata-structure"&gt;Metadata Standards&lt;/a&gt; get introduced. Following these standards are required for Opensea to read and display your metadata, you do not want a blank image for an NFT.&lt;/p&gt;

&lt;p&gt;Every token URI is gonna be a JSON file looking something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "description": "Friendly OpenSea Creature that enjoys long swims in the ocean.", 
  "external_url": "https://openseacreatures.io/3", 
  "image": "https://storage.googleapis.com/opensea-prod.appspot.com/puffs/3.png", 
  "name": "Dave Starbelly",
  "attributes": [ ... ], 
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Opensea is specifically looking for the names above, 'image', 'name' etc. &lt;/p&gt;

&lt;p&gt;I will be using Name, Desc and Image. If you want to try audio and video, &lt;strong&gt;animation_url&lt;/strong&gt; is the one as mentioned in the standards page I linked above. The image or animation url will point to another resource, also on IPFS. &lt;strong&gt;This is the image or video that will appear on Opensea&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As well as NFT metadata, there is &lt;strong&gt;Collection&lt;/strong&gt; metadata fetched from the &lt;code&gt;contractUri()&lt;/code&gt; function in the GameItem.sol contract. Each NFT contract is a Collection. Each minted token on the contract is an NFT. We will need to upload metadata for the Collection in the form of, image, name, desc. &lt;/p&gt;

&lt;h2&gt;
  
  
  Create and upload token metadata
&lt;/h2&gt;

&lt;p&gt;Now that we know the guidance on NFT metadata, we shall write some up before deploying any contracts. Because of IPFS, I have decided to organise my folders, separating collection data from nft data. I follow this pattern because I usually mint more than 1 nft, therefore I want to upload my media in folders. Feel free to organise them in any way you want.&lt;/p&gt;

&lt;p&gt;Start by creating 2 folders in the root of the project. collection-data and nft-data, you should consider adding this to gitignore if you ever push this to GitHub. Within collection-data, have your collection image and json file like so:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fce6xs2o1ib1tgctlpqay.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fce6xs2o1ib1tgctlpqay.png" alt="collection-data-image" width="778" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Of course, use your own values. The external_link is not crucial, but worth testing, and say if you leave name empty, Opensea will make a name. &lt;/p&gt;

&lt;p&gt;As you may notice the image value is empty. We need to upload the collection image first, to get the image URI for the JSON file to point to, which we will upload next. Despite that they are together in a folder in the project, the image needs to be uploaded before the json.&lt;/p&gt;

&lt;p&gt;Once you have your test collection image ready, open up Pinata IPFS from the prerequisites and upload it. After logging in, you will land straight at the uploading page. Click &lt;em&gt;Upload a File&lt;/em&gt; and pick the collection image from your project in the file explorer.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs0v3z6ltxw4sewjfem6m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs0v3z6ltxw4sewjfem6m.png" alt="collection-image-upload" width="800" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In your dashboard, you will see the file has a CID or Content Identifier. As described in the &lt;a href="https://docs.ipfs.io/concepts/content-addressing/"&gt;IPFS docs&lt;/a&gt;, the CID is an address/hash based on the content, not a location. Not necessarily important for us but interesting nonetheless. &lt;/p&gt;

&lt;p&gt;Clicking on the image will send you to a pinata gateway url. I have had my best experiences in using this URI format: &lt;code&gt;https://ipfs.io/ipfs/your-collection-cid&lt;/code&gt;. Copy this, and your CID from Pinata and paste it into the collection JSON in your project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
      "name": "Collection Name",
      "description": "A test collection for ERC721 tutorial",
      "image": 
"https://ipfs.io/ipfs/QmQ2CPtFwRxoASHmiqbTPSfuPr91NfbMw2fjPtgvz55LPL"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can do the same for your nft-data. Upload the test nft image first, then copy and paste the cid into 'nft.json'. The JSON may look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "name": "Example Coffee #1",
    "description": "I am a coffee but, this .jpg extension allows me to be warm forever.",
    "image": "https://ipfs.io/ipfs/QmSXSHaUDJTorFReSJA24HjruRo2yqYbxPUSbxG7xTi31c"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, you can upload your JSON files for both collection, and nft[s]. When minting &lt;strong&gt;multiple&lt;/strong&gt; NFTs, I like to upload all my media in one folder, so the uri will look like: &lt;code&gt;https://ipfs.io/ipfs/folder-hash/nft1.jpg&lt;/code&gt;. However, for this post I shall upload 1 jpg.&lt;/p&gt;

&lt;p&gt;With that, we are done with the metadata. You will need the collection and NFT JSON CIDs for the next stage, when we will deploy and mint, ooh exciting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deploying and Minting the NFT
&lt;/h2&gt;

&lt;p&gt;With the metadata and environment all set, we can begin this stage by viewing the GameItem.sol in the contracts folder of the project. It will look like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pragma solidity ^0.8.0;

import "../node_modules/@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "../node_modules/@openzeppelin/contracts/utils/Counters.sol";
import "../node_modules/@openzeppelin/contracts/access/Ownable.sol";

contract GameItem is ERC721URIStorage, Ownable {
    using Counters for Counters.Counter;
    Counters.Counter private _tokenIds;

    // set contract name and ticker. 
    constructor() ERC721("Contract Name", "TIC") {}

    //get the current supply of tokens
    function totalSupply() public view returns (uint256) {
        return _tokenIds.current();
    }

    // for opensea collection 
    function contractURI() public pure returns (string memory) {
        return "https://ipfs.io/ipfs/your-collection-ipfshash";
    }


    function mintItem(address player, string memory tokenURI)
        public
        onlyOwner
        returns (uint256)
    {
        _tokenIds.increment();
        uint256 newItemId = _tokenIds.current();
        _mint(player, newItemId);
        _setTokenURI(newItemId, tokenURI);
        return newItemId;
    }

}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you are new to Solidity, there is a bit to talk about here. Starting with pragma. Pragma simply sets the solidity compiler version to use when compiling the file. The project is using 0.8.0, the highest minor version of Solidity available, which can be set in the truffle-config.js.&lt;/p&gt;

&lt;p&gt;We are then importing Ownable, for modifying function calls to owners only (you, the deployer), then Counters for the tokenId's, this is a trusted utility for keeping track of tokens safely. ERC721URIStorage inherits the classic ERC721 interface, and adds some token URI help to the contract, recently added in Openzeppelin version 4.x . You should definitely have a look at these libraries, and abstract contracts, as they are great examples for building your own interfaces.&lt;/p&gt;

&lt;p&gt;The most important bit for us, is the contractURI function. As I was saying earlier, 1 ERC-721 contract is 1 collection. This function returns a string that is the URI to your collection JSON. Opensea will call this method when displaying your collection on their frontend. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Copy your collection JSON ipfs URI into the return statement&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function contractURI() public pure returns (string memory) {
        return "https://ipfs.io/ipfs/your-collection-ipfshash";
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Optionally, you may set the ticker and the token/contract name in the Constructor function. This function is ran once at deployment for initialising something. In our case, its inheriting ERC-721 through ERC721URIStorage, expecting ticker and name arguments. This a test, so I shall leave it default.&lt;/p&gt;

&lt;p&gt;Providing your wallet phrase and node url are in the .env file, we can now deploy this contract. Open a new terminal in the project and enter &lt;code&gt;truffle develop&lt;/code&gt;. Powershell might need the &lt;code&gt;npx&lt;/code&gt; prefix. This command will prep the truffle cli for deploying, compiling and more. You could enter &lt;code&gt;compile&lt;/code&gt; for a single compile without having to deploy, but when you deploy, truffle will compile anyway. &lt;/p&gt;

&lt;p&gt;To deploy run &lt;code&gt;migrate --network mumbai&lt;/code&gt; in the terminal. ** You may experience errors here**, especially with specific environments. These tools are certainly not perfect. A good troubleshoot would be to run migrate --network development to eliminate where the error is.&lt;/p&gt;

&lt;p&gt;I got this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Starting migrations...
======================
&amp;gt; Network name:    'mumbai'
&amp;gt; Network id:      80001
&amp;gt; Block gas limit: 20000000 (0x1312d00)


1_initial_migration.js
======================

   Replacing 'Migrations'
   ----------------------
   &amp;gt; transaction hash:    0x4f703c7184a36b92af5fdd5d7751a7ed444670031475dfc90009927b96949d82
   &amp;gt; Blocks: 2            Seconds: 8
   &amp;gt; contract address:    0xb6e5A1B174C1CA435cB43Cf61fF9064F87f5f0Ec
   &amp;gt; block number:        18792256
   &amp;gt; block timestamp:     1631363185
   &amp;gt; account:             0x5f4c3843495Babe89cB3516cEbD8840024e741fa
   &amp;gt; balance:             1.408520183748380055
   &amp;gt; gas used:            245600 (0x3bf60)
   &amp;gt; gas price:           3 gwei
   &amp;gt; value sent:          0 ETH
   &amp;gt; total cost:          0.0007368 ETH

   Pausing for 2 confirmations...
   ------------------------------
   &amp;gt; confirmation number: 2 (block: 18792258)

   &amp;gt; Saving migration to chain.
   &amp;gt; Saving artifacts
   -------------------------------------
   &amp;gt; Total cost:           0.0007368 ETH


2_deploy_token.js
=================

   Replacing 'GameItem'
   --------------------
   &amp;gt; transaction hash:    0x2a0bc70f5c77c9c28e4a237de7adf72bac55c5d05d744a013c1dbd67fd1f245b
   &amp;gt; Blocks: 2            Seconds: 4
   &amp;gt; contract address:    0x87E67eBEBb785060d4Ed85Bff7E67dEc9Efa87F4
   &amp;gt; block number:        18792264
   &amp;gt; block timestamp:     1631363201
   &amp;gt; account:             0x5f4c3843495Babe89cB3516cEbD8840024e741fa
   &amp;gt; balance:             1.400152706748380055
   &amp;gt; gas used:            2743246 (0x29dbce)
   &amp;gt; gas price:           3 gwei
   &amp;gt; value sent:          0 ETH
   &amp;gt; total cost:          0.008229738 ETH

   Pausing for 2 confirmations...
   ------------------------------
   &amp;gt; confirmation number: 2 (block: 18792266)

   &amp;gt; Saving migration to chain.
   &amp;gt; Saving artifacts
   -------------------------------------
   &amp;gt; Total cost:         0.008229738 ETH


Summary
=======
&amp;gt; Total deployments:   2
&amp;gt; Final cost:          0.008966538 ETH


- Blocks: 0            Seconds: 0
- Saving migration to chain.
- Blocks: 0            Seconds: 0
- Saving migration to chain.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do not close the terminal, we are not done here. Above you can see that Truffle ran the Migration script, to deploy the Migrations.sol contract, which is follwed by the token script. This is truffle's way of deploying contracts. You could order more deployments by creating more js scripts in the migrations folder of the project. If you're deployment was successful, very well done to you, you have deployed your contract.&lt;/p&gt;

&lt;p&gt;We need the token contract address for minting, and you could get this from the Mumbai Tesnet &lt;a href="https://mumbai.polygonscan.com/"&gt;Block Explorer&lt;/a&gt;, under your address. Conveniently, the address was printed to the console by truffle after deployment to the blockchain. &lt;/p&gt;

&lt;p&gt;Copy the &lt;code&gt;contract address: your token address&lt;/code&gt; line from the console under the 2_deploy_token.js log. Paste this into your scripts/mint.js file on line 13 like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const NFT_CONTRACT_ADDRESS = "0x87E67eBEBb785060d4Ed85Bff7E67dEc9Efa87F4"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The web3 script will need this constant variable for instantiating the contract, to call/send methods on it. &lt;/p&gt;

&lt;p&gt;The script will also need YOUR account address in the OWNER_ADDRESS variable to mint to YOU, and for you to send this transaction.&lt;/p&gt;

&lt;p&gt;You may notice that we are reading the contract artifact JSON with fs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let rawdata = fs.readFileSync(path.resolve(__dirname, "../build/contracts/GameItem.json"));
let contractAbi = JSON.parse(rawdata);
const NFT_ABI = contractAbi.abi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;This might need to be reworked for Linux and MACos. I am not super experienced with linux file systems&lt;/strong&gt;. All the script is doing here is reading the contract ABI from another file in the project&lt;/p&gt;

&lt;p&gt;Web3.js will need this JSON for reference when calling/sending. Therefore, if you compiled a completely different contract in the same project, you would overwrite the artifacts. &lt;strong&gt;Make a new project for new contracts after you're finished with this one&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For the final requirement of this script, you need the CID hash of the NFT JSON you uploaded to Pinata IPFS earlier for the argument of the mintItem function. Paste it into your script here on line 43:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;await nftContract.methods
.mintItem(OWNER_ADDRESS, `https://ipfs.io/ipfs/your-tokenjson-cid`)
.send({ from: OWNER_ADDRESS })
.then(console.log('minted'))
.catch(error =&amp;gt; console.log(error));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the script ready, run &lt;code&gt;node scripts/mint.js&lt;/code&gt; in the project terminal. You can open a new terminal to do this or press CTRL+C to exit the truffle cli in the current terminal.&lt;/p&gt;

&lt;p&gt;Provided that there are no errors here, 'Minted' should be printed to console and you can check your account on the block explorer to ensure that it was minted. Post any errors in the comments and google them.&lt;/p&gt;

&lt;p&gt;With your Metamask logged in on your browser, let's view our NFT on Opensea via an existing contract. Go to the &lt;a href="https://testnets.opensea.io/"&gt;Opensea Testnet&lt;/a&gt; frontend. Open the profile icon dropdown to sign in, then click My Collections:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fez7y9tgx2akd7qrpqsnn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fez7y9tgx2akd7qrpqsnn.png" alt="Opensea-Home" width="800" height="325"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, tap the 3 dots menu icon, next to Create a Collection, then 'import an existing contract'. You will then be asked whether the nft is on a mainnet, testnet. Select &lt;strong&gt;testnet&lt;/strong&gt; of course.&lt;/p&gt;

&lt;p&gt;Now you can pass your nft contract address into the field, and select 'Mumbai' in the dropdown on the left like so: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg9lnnmdgrxvhjbkziftd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg9lnnmdgrxvhjbkziftd.png" alt="Existing-contract-opensea" width="800" height="169"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You may receive the following message: 'We couldn't find this contract. Please ensure that this is a valid ERC721 or ERC1155 contract deployed on Mumbai and that you have already minted items on the contract'.&lt;/p&gt;

&lt;p&gt;This is a common issue, as Opensea will display your tokens when they can. As long as you can see the token contract and transactions on Polygon Scan, you know it is a valid ERC-721 contract and has minted 1 item. &lt;a href="https://forum.openzeppelin.com/t/how-to-view-nft-deployed-and-minted-on-mumbai-testnet-on-opensea-testnet/10299"&gt;Some dev's&lt;/a&gt; have waited 24 hours + to get their NFTs to appear.&lt;/p&gt;

&lt;p&gt;Here is &lt;a href="https://testnets.opensea.io/assets/mumbai/0x87e67ebebb785060d4ed85bff7e67dec9efa87f4/1"&gt;my NFT&lt;/a&gt;. I made the mistake of not adding the collection hash to the contractURI function in my first attempt. Despite redeploying the contract with the fix, Opensea still cant read the collection metadata. Fortunately, you can change this by editing the collection. At least my 'Example Coffee' NFT metadata worked.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final notes and Conclusion
&lt;/h2&gt;

&lt;p&gt;With all the action behind us, let's have a review.&lt;/p&gt;

&lt;p&gt;You have learnt a simple way of deploying ERC-721 tokens to the Polygon testnet, nice. You can repeat this process for Matic mainnet, providing you have MATIC tokens on your mainnet balance, and you edit your mint script to instantiate with the &lt;code&gt;MATIC&lt;/code&gt; keyword as oppose to &lt;code&gt;MUMBAI&lt;/code&gt; on line 31 of mint.js. &lt;/p&gt;

&lt;p&gt;There are few extras that I missed for this tutorial. &lt;/p&gt;

&lt;p&gt;Firstly, I could have verified the contracts for a more professional look. Although, it is easier to do this in Hardhat, despite the fact that I cannot get a working example with Hardhat yet. Truffle requires more configuration for verifying contracts, therefore I will leave this for the next tutorial. &lt;/p&gt;

&lt;p&gt;Optionally, you can add extra code to your contract to avoid gas fees when selling items from Opensea. &lt;a href="https://docs.opensea.io/docs/polygon-basic-integration"&gt;The Opensea documentation&lt;/a&gt; explains how to work it. Simply, you set Opensea's matic contract address as your operator for your contract. With this, Opensea can transfer NFTs for you, saving you, or any owner gas.&lt;/p&gt;

&lt;p&gt;In addition to these extras, you might want to check out &lt;a href="https://support.opensea.io/hc/en-us/articles/1500012270982-What-is-Freezing-Metadata-#:~:text=Freezing%20your%20metadata%20will%20permanently,never%20be%20lost%20or%20missing."&gt;freezing your metadata&lt;/a&gt; in production. This is a feature by Opensea to stop mutable metadata. NFT buyers and sellers will be  comforted to see that their metadata is frozen.&lt;/p&gt;

&lt;p&gt;Finally, I would like to guide you towards bigger and better tutorials with these links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md"&gt;ERC-721 doc - The old standard we used&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1155.md"&gt;ERC-1155 doc - The improved community standard for fungible AND non-fungibles&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=tBMk1iZa85Y"&gt;Filip from Moralis on ERC-1155&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  I wish you the best and hope you learn't something.
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Edit
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://github.com/YourNewEmpire/Hardhat-OpenSea-Boilerplate"&gt;New Hardhat repo with OpenSea MetaTXs and support for ERC-1155/721&lt;/a&gt;
&lt;/h3&gt;

</description>
      <category>javascript</category>
      <category>solidity</category>
      <category>opensea</category>
      <category>ethereum</category>
    </item>
  </channel>
</rss>
