<?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>Forem: thirdweb</title>
    <description>The latest articles on Forem by thirdweb (@thirdweb).</description>
    <link>https://forem.com/thirdweb</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%2Forganization%2Fprofile_image%2F5087%2Fa22e0f35-f97b-4315-b0ca-7574cb45b73d.png</url>
      <title>Forem: thirdweb</title>
      <link>https://forem.com/thirdweb</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/thirdweb"/>
    <language>en</language>
    <item>
      <title>Deploy a Smart Contract on Ethereum (ETH)</title>
      <dc:creator>Avneesh Agarwal</dc:creator>
      <pubDate>Mon, 27 Mar 2023 21:15:40 +0000</pubDate>
      <link>https://forem.com/thirdweb/deploy-a-smart-contract-on-ethereum-eth-28e3</link>
      <guid>https://forem.com/thirdweb/deploy-a-smart-contract-on-ethereum-eth-28e3</guid>
      <description>&lt;p&gt;This guide will show you how to deploy any smart contract to the &lt;a href="https://ethereum.org/en/"&gt;&lt;strong&gt;Ethereum&lt;/strong&gt;&lt;/a&gt; network.&lt;/p&gt;

&lt;p&gt;By the end, you'll learn how to create a simple NFT Drop smart contract, deploy it to the &lt;a href="https://thirdweb.com/sepolia?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=deploy-contract-ethereum"&gt;&lt;strong&gt;Sepolia&lt;/strong&gt;&lt;/a&gt; testnet, and mint an NFT on the smart contract.&lt;/p&gt;

&lt;p&gt;Let's get started!&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Ethereum?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://ethereum.org/en/?ref=thirdweb"&gt;Ethereum&lt;/a&gt; is the most popular blockchain for web3 applications. It is a Layer 1 blockchain, meaning it is highly secure, but it is also very expensive to use when compared to other alternatives.&lt;/p&gt;

&lt;p&gt;The Ethereum network has projects such as the &lt;a href="https://boredapeyachtclub.com/?ref=thirdweb#/"&gt;Bored Ape Yacht Club&lt;/a&gt; and &lt;a href="https://www.larvalabs.com/cryptopunks?ref=thirdweb"&gt;Crypto Punks&lt;/a&gt; which have helped Ethereum projects gain a large community of users.&lt;/p&gt;

&lt;p&gt;Projects that don't require a lot of interaction with the blockchain are typically more suitable for Ethereum as a result of the network's high gas fees.&lt;/p&gt;

&lt;p&gt;If you take a look at our &lt;a href="https://thirdweb.com/gas?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=deploy-contract-ethereum"&gt;Gas Estimator&lt;/a&gt;, you can quickly see that Ethereum smart contracts are both expensive for you to deploy and expensive for your users to interact with.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create a smart contract on Ethereum
&lt;/h2&gt;

&lt;p&gt;To begin, head to the Contracts page in your thirdweb Dashboard and hit "Deploy new contract":&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--POj_lrnE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/SCR-20230304-uu3-1-.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--POj_lrnE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/SCR-20230304-uu3-1-.png" alt="deploy new contract" width="880" height="199"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You will be taken to our &lt;a href="https://thirdweb.com/explore?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=deploy-contract-ethereum"&gt;Explore&lt;/a&gt; page — where you can browse smart contracts built by the top protocols in web3 and deploy them in just a few clicks!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: You can also use the thirdweb&lt;/em&gt; &lt;a href="https://portal.thirdweb.com/cli?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=deploy-contract-ethereum"&gt;&lt;em&gt;CLI&lt;/em&gt;&lt;/a&gt; &lt;em&gt;to set up a smart contract environment by running the below command from your terminal:&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This will take you through an easy-to-follow flow of steps for you to create your contract. Learn more about this in our&lt;/em&gt; &lt;a href="https://blog.thirdweb.com/guides/the-ultimate-guide-to-thirdweb-cli/?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=deploy-contract-ethereum"&gt;&lt;em&gt;CLI guide&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Otherwise, let's get back to &lt;a href="https://thirdweb.com/explore?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=deploy-contract-ethereum"&gt;Explore&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KbxD94RR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/SCR-20230309-bpg-2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KbxD94RR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/SCR-20230309-bpg-2.png" alt="thirdweb explore page" width="880" height="485"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here, select your smart contract of choice. For this guide, we're going to use the &lt;a href="https://thirdweb.com/thirdweb.eth/DropERC721?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=deploy-contract-ethereum"&gt;NFT Drop (ERC721)&lt;/a&gt; contract to create our NFT collection:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--R47lbuAI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/SCR-20230304-rkv-2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--R47lbuAI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/SCR-20230304-rkv-2.png" alt="thirdweb's NFT Drop Contract" width="880" height="483"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Set up your smart contract with an image, name, description, etc., and configure which wallet address will receive the funds from primary and secondary sales:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HXL0k14A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/contract-metadata-2-1-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HXL0k14A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/contract-metadata-2-1-1.png" alt="Populate metadata of your contract" width="880" height="462"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our smart contracts are deployable to any EVM chain, so let's deploy this to the Sepolia testnet!&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Add the Sepolia network to your dashboard &amp;amp; wallet&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;To deploy a smart contract to Ethereum (more specifically, to the &lt;a href="https://thirdweb.com/sepolia?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=deploy-contract-ethereum"&gt;Sepolia&lt;/a&gt; testnet) we first need to add it as a network to the &lt;a href="https://thirdweb.com/dashboard?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=deploy-contract-ethereum"&gt;Dashboard&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To do this, click the &lt;code&gt;Configure Networks&lt;/code&gt; button here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6H2s_PEq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/Click-on-Configure-Networks-to-add-Sepolia.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6H2s_PEq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/Click-on-Configure-Networks-to-add-Sepolia.png" alt="Click on Configure Networks to add Sepolia" width="880" height="373"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Search for "Sepolia" and select it:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qKe1p1YW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/Search-for-Sepolia.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qKe1p1YW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/Search-for-Sepolia.png" alt="Search for Sepolia" width="880" height="711"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It will now auto-fill all the details required. You can upload an icon for the Testnet if you like and use a custom RPC you can use as well.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--d6tjzrbK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/Add-Sepolia-Testnet-to-the-dashboard.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--d6tjzrbK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/Add-Sepolia-Testnet-to-the-dashboard.png" alt="Add metadata of Sepolia network" width="880" height="731"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on "Add Network" and voilá! You will now see that Sepolia has been added to the Testnets section of the Your Networks module:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Oa3LHcP1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/Select-Sepolia-network.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Oa3LHcP1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/Select-Sepolia-network.png" alt="You can now see Sepolia network added to the list" width="880" height="780"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Get Sepolia ETH in your wallet
&lt;/h2&gt;

&lt;p&gt;Head over to the &lt;a href="https://sepoliafaucet.com"&gt;Sepolia Faucet&lt;/a&gt; here, paste your wallet address and click on "Send me ETH":&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zfvgTv7---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/Request-Sepolia-Faucet-funds.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zfvgTv7---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/Request-Sepolia-Faucet-funds.png" alt="Sepolia faucet" width="880" height="483"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you have completed this process, you will have testnet funds in your wallet on Sepolia Testnet, meaning you're now ready to deploy your smart contract!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--481FzxBM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/image-97.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--481FzxBM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/image-97.png" alt="Funds on Sepolia Testnet" width="538" height="112"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Deploying the contract
&lt;/h2&gt;

&lt;p&gt;Now that you have your testnet ETH, let's go back to the thirdweb Dashboard where we were building our &lt;a href="https://thirdweb.com/thirdweb.eth/DropERC721?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=deploy-contract-ethereum"&gt;&lt;strong&gt;NFT Drop&lt;/strong&gt;&lt;/a&gt; contract.&lt;/p&gt;

&lt;p&gt;We have already filled out the metadata so click on "Deploy Now" after selecting the chain. It will prompt you to two transactions, you have to approve them.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LshnxQr0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/Deploy-contract-to-sepolia-testnet.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LshnxQr0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/Deploy-contract-to-sepolia-testnet.png" alt="Confirm the transaction to deploy the contract" width="880" height="508"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And you're done! You have just deployed to the Sepolia Testnet.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Calling Smart Contract Functions&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Let's see how we can use the smart contract by calling some functions on it, such as minting an NFT into our collection!&lt;/p&gt;

&lt;p&gt;From the &lt;code&gt;Explorer&lt;/code&gt; tab, you can view all of the available functions on your smart contract and execute them directly from your connected wallet:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1QhefXN6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/contract-explorer-2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1QhefXN6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/contract-explorer-2.png" alt="Calling the Read name function from Explorer" width="880" height="478"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting Up Our NFT Collection
&lt;/h3&gt;

&lt;p&gt;In our example, we created an NFT drop smart contract, so we'll quickly set it up and mint our first NFT by performing the following steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://portal.thirdweb.com/pre-built-contracts/nft-drop?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=deploy-contract-ethereum#lazy-minting-nfts"&gt;Lazy mint&lt;/a&gt; a batch of NFTs.&lt;/li&gt;
&lt;li&gt;Configuring our &lt;a href="https://portal.thirdweb.com/pre-built-contracts/nft-drop?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=deploy-contract-ethereum#setting-claim-phases"&gt;claim conditions&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Mint an NFT from the drop!&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We won't go into too much detail about this process in this guide, check out our other &lt;a href="https://blog.thirdweb.com/tag/nft-drop/?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=deploy-contract-ethereum"&gt;NFT Drop Guides&lt;/a&gt; for more information!&lt;/p&gt;

&lt;p&gt;Once we've set up our NFTs, we can click the &lt;code&gt;Claim&lt;/code&gt; button in the &lt;code&gt;NFTs&lt;/code&gt; tab to mint our first NFT, and voilà! We just minted an NFT on the Sepolia testnet!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--h48X9mpF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/image-94.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--h48X9mpF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/image-94.png" alt="Claimed NFT" width="880" height="295"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What's Next?
&lt;/h3&gt;

&lt;p&gt;Now that you've deployed your smart contract, you can use our &lt;a href="https://portal.thirdweb.com/sdk?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=deploy-contract-ethereum"&gt;SDK&lt;/a&gt; to build a web3 application! Where users can connect their wallets and interact with the functions of your smart contracts. Learn more from our guide below:&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Wrapping up&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In this guide, you've learned how to create a simple NFT Drop smart contract, deploy it to the &lt;a href="https://thirdweb.com/sepolia?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=deploy-contract-ethereum"&gt;Sepolia&lt;/a&gt; testnet, and mint an NFT on the smart contract. We hope it was helpful!&lt;/p&gt;

&lt;p&gt;If you have any questions jump into the &lt;a href="https://discord.gg/thirdweb"&gt;&lt;strong&gt;thirdweb Discord&lt;/strong&gt;&lt;/a&gt; and join 32,000+ other builders! And if you're looking to build on Ethereum and want to learn more about how to do that with thirdweb's tools, &lt;a href="https://thirdweb.typeform.com/to/ZV3gUhiP"&gt;&lt;strong&gt;reach out&lt;/strong&gt;&lt;/a&gt; to the team directly. Please let us know if you have any feature requests or guide requests &lt;a href="https://feedback.thirdweb.com/"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>web3</category>
      <category>nft</category>
      <category>evm</category>
      <category>ethereum</category>
    </item>
    <item>
      <title>Deploy a Smart Contract on Polygon (MATIC)</title>
      <dc:creator>Avneesh Agarwal</dc:creator>
      <pubDate>Mon, 27 Mar 2023 21:15:13 +0000</pubDate>
      <link>https://forem.com/thirdweb/deploy-a-smart-contract-on-polygon-matic-1bpc</link>
      <guid>https://forem.com/thirdweb/deploy-a-smart-contract-on-polygon-matic-1bpc</guid>
      <description>&lt;p&gt;This guide will show you how to deploy any smart contract to the &lt;a href="https://www.polygon.technology"&gt;Polygon&lt;/a&gt; network.&lt;/p&gt;

&lt;p&gt;By the end, you'll learn how to create a simple NFT Drop smart contract, deploy it to the &lt;a href="https://thirdweb.com/mumbai?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=deploy-contract-polygon"&gt;Polygon Mumbai&lt;/a&gt; testnet, and mint an NFT on the smart contract.&lt;/p&gt;

&lt;p&gt;Let's get started!&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Polygon?
&lt;/h2&gt;

&lt;p&gt;Polygon has exponentially lower (approximately ~10,000x lower) gas fees than Ethereum does, and utilises Proof-of-Stake (POS) consensus, which has a less negative impact on the environment than Proof-of-Work (POW).&lt;/p&gt;

&lt;p&gt;Using Polygon is a great choice for all kinds of blockchain projects,especially those that require a lot of interaction with the blockchain; because of its low gas fees.&lt;/p&gt;

&lt;p&gt;Brands such as &lt;a href="https://about.fb.com/news/2022/05/introducing-digital-collectibles-to-showcase-nfts-instagram/?ref=thirdweb"&gt;Instagram&lt;/a&gt; and &lt;a href="https://news.adidas.com/originals/adidas-originals-and-prada-announce-a-first-of-its-kind-open-metaverseuser-generated-nft-project/s/30a29dad-6ded-4302-ae40-f9f2338e7298?ref=thirdweb"&gt;Adidas&lt;/a&gt; have recently started using Polygon for their projects, adding credibility and a growing audience for the Polygon network.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create a smart contract on Polygon
&lt;/h2&gt;

&lt;p&gt;To begin, head to the Contracts page in your thirdweb Dashboard and hit "Deploy new contract":&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--POj_lrnE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/SCR-20230304-uu3-1-.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--POj_lrnE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/SCR-20230304-uu3-1-.png" alt="deploy new contract" width="880" height="199"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You will be taken to our &lt;a href="https://thirdweb.com/explore?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=deploy-contract-polygon"&gt;Explore&lt;/a&gt; page — where you can browse smart contracts built by the top protocols in web3 and deploy them in just a few clicks!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: You can also use the thirdweb&lt;/em&gt; &lt;a href="https://portal.thirdweb.com/cli?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=deploy-contract-polygon"&gt;&lt;em&gt;CLI&lt;/em&gt;&lt;/a&gt; &lt;em&gt;to set up a smart contract environment by running the below command from your terminal:&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This will take you through an easy-to-follow flow of steps for you to create your contract. Learn more about this in our&lt;/em&gt; &lt;a href="https://blog.thirdweb.com/guides/the-ultimate-guide-to-thirdweb-cli/"&gt;&lt;em&gt;CLI guide&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Otherwise, let's get back to &lt;a href="https://thirdweb.com/explore?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=deploy-contract-polygon"&gt;Explore&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KbxD94RR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/SCR-20230309-bpg-2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KbxD94RR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/SCR-20230309-bpg-2.png" alt="thirdweb explore page" width="880" height="485"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here, select your smart contract of choice. For this guide, we're going to use the &lt;a href="https://thirdweb.com/thirdweb.eth/DropERC721?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=deploy-contract-polygon"&gt;NFT Drop (ERC721)&lt;/a&gt; contract to create our NFT collection:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--R47lbuAI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/SCR-20230304-rkv-2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--R47lbuAI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/SCR-20230304-rkv-2.png" alt="thirdweb's NFT Drop Contract" width="880" height="483"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Set up your smart contract with an image, name, description, etc., and configure which wallet address will receive the funds from primary and secondary sales:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HXL0k14A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/contract-metadata-2-1-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HXL0k14A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/contract-metadata-2-1-1.png" alt="Populate metadata of your contract" width="880" height="462"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the network/chain section select Polygon Mainnet or Polygon Mumbai (testnet) as you wish. For the sake of this guide, I am going to use Polygon Mumbai&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WF2zKRIx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/select-mumbai-network-2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WF2zKRIx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/select-mumbai-network-2.png" alt="Select Polygon Mumbai network" width="880" height="462"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you have selected the network, click on deploy now. It will prompt you to switch your network to Mumbai&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wfCNP1Me--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/SCR-20230309-k6h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wfCNP1Me--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/SCR-20230309-k6h.png" alt="Switch Wallet to Polygon Mumbai Testnet" width="880" height="460"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on the switch Wallet button and if you don't already have the network in your wallet it will prompt you to add the network and then switch to the network:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QCcbsaRk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/add-polygon-mumbai-to-wallet-2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QCcbsaRk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/add-polygon-mumbai-to-wallet-2.png" alt="Switch network to Polygon Mumbai" width="880" height="462"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now let's deploy the smart contract on the Polygon Mumbai testnet! But before that, we need testnet funds.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Get Mumbai matic in your wallet&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Once you have added the Mumbai network to your wallet. You can either navigate there &lt;a href="https://faucet.polygon.technology"&gt;directly&lt;/a&gt; or open the Wallet button and hit &lt;strong&gt;"Request Testnet Funds"&lt;/strong&gt; in the thirdweb dashboard:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mnJD2QLt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/SCR-20230309-k9s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mnJD2QLt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/SCR-20230309-k9s.png" alt="Click on Request Testnet Funds from the dropdown" width="792" height="782"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This will take you to the Polygon Mumbai faucet. Here, paste your wallet address and hit submit&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IWu1bs2g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/polygon-mumbai-faucet.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IWu1bs2g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/polygon-mumbai-faucet.png" alt="" width="880" height="481"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You will be prompted to review the details and confirm:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eRuw3VWF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/confirm-details-2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eRuw3VWF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/confirm-details-2.png" alt="Confirm the details of your request" width="880" height="462"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you confirm the details, funds will arrive in your wallet:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rPH9vpdg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/submit-request-2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rPH9vpdg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/submit-request-2.png" alt="Request for funds submitted" width="880" height="462"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you have completed this process, you will have testnet funds in your wallet on Mumbai testnet, meaning you're now ready to deploy your smart contract!&lt;/p&gt;

&lt;h2&gt;
  
  
  Deploying the contract
&lt;/h2&gt;

&lt;p&gt;Now that you have your testnet ETH, let's go back to the thirdweb Dashboard where we were building our &lt;a href="https://thirdweb.com/thirdweb.eth/DropERC721?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=deploy-contract-polygon"&gt;&lt;strong&gt;NFT Drop&lt;/strong&gt;&lt;/a&gt; contract.&lt;/p&gt;

&lt;p&gt;We have already filled out the metadata so click on "Deploy Now" after selecting the chain. It will prompt a transaction, you have to approve that.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Qh-rbVu2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/SCR-20230309-kko-2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Qh-rbVu2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/SCR-20230309-kko-2.png" alt="Confirm the transaction to deploy the contract" width="880" height="505"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And you're done! You have just deployed to the Polygon Mumbai testnet.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Calling Smart Contract Functions&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Let's see how we can use the smart contract by calling some functions on it, such as minting an NFT into our collection!&lt;/p&gt;

&lt;p&gt;From the &lt;code&gt;Explorer&lt;/code&gt; tab, you can view all of the available functions on your smart contract and execute them directly from your connected wallet:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1QhefXN6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/contract-explorer-2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1QhefXN6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/contract-explorer-2.png" alt="Calling the Read name function from Explorer" width="880" height="478"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting Up Our NFT Collection
&lt;/h3&gt;

&lt;p&gt;In our example, we created an NFT drop smart contract, so we'll quickly set it up and mint our first NFT by performing the following steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://portal.thirdweb.com/pre-built-contracts/nft-drop?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=deploy-contract-polygon#lazy-minting-nfts"&gt;Lazy mint&lt;/a&gt; a batch of NFTs.&lt;/li&gt;
&lt;li&gt;Configuring our &lt;a href="https://portal.thirdweb.com/pre-built-contracts/nft-drop?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=deploy-contract-polygon#setting-claim-phases"&gt;claim conditions&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Mint an NFT from the drop!&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once we've set up our NFTs, we can click the &lt;code&gt;Claim&lt;/code&gt; button in the &lt;code&gt;NFTs&lt;/code&gt; tab to mint our first NFT, and voilà! We just minted an NFT on the Polygon testnet!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--h48X9mpF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/image-94.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--h48X9mpF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.thirdweb.com/content/images/2023/03/image-94.png" alt="Claimed NFT" width="880" height="295"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What's Next?
&lt;/h3&gt;

&lt;p&gt;Now that you've deployed your smart contract, you can use our &lt;a href="https://portal.thirdweb.com/sdk?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=deploy-contract-polygon"&gt;SDK&lt;/a&gt; to build a web3 application! Where users can connect their wallets and interact with the functions of your smart contracts. Learn more from our guide below:&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Wrapping up&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In this guide, you've learned how to create a simple NFT Drop smart contract, deploy it to the &lt;a href="https://thirdweb.com/mumbai?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=deploy-contract-polygon"&gt;Polygon Mumbai&lt;/a&gt; testnet, and mint an NFT on the smart contract. We hope it was helpful!&lt;/p&gt;

&lt;p&gt;If you have any questions jump into the &lt;a href="https://discord.gg/thirdweb"&gt;&lt;strong&gt;thirdweb Discord&lt;/strong&gt;&lt;/a&gt; and join 32,000+ other builders! And if you're looking to build on Polygon and want to learn more about how to do that with thirdweb's tools, &lt;a href="https://thirdweb.typeform.com/to/ZV3gUhiP"&gt;&lt;strong&gt;reach out&lt;/strong&gt;&lt;/a&gt; to the team directly. Please let us know if you have any feature requests or guide requests &lt;a href="https://feedback.thirdweb.com/?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=deploy-contract-polygon"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>polygon</category>
      <category>evm</category>
      <category>thirdweb</category>
      <category>web3</category>
    </item>
    <item>
      <title>Sign In with Solana - Authenticate Users with their Phantom Wallet</title>
      <dc:creator>Avneesh Agarwal</dc:creator>
      <pubDate>Thu, 13 Oct 2022 01:36:16 +0000</pubDate>
      <link>https://forem.com/thirdweb/sign-in-with-solana-authenticate-users-with-their-phantom-wallet-4b21</link>
      <guid>https://forem.com/thirdweb/sign-in-with-solana-authenticate-users-with-their-phantom-wallet-4b21</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In this guide, we are going to use thirdweb auth to add sign in with Solana to our Dapps!&lt;/p&gt;

&lt;p&gt;Before we get started, below are some helpful resources where you can learn more about the tools we will use in this guide.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/thirdweb-example/sign-in-with-solana" rel="noopener noreferrer"&gt;View project source code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://portal.thirdweb.com/solana" rel="noopener noreferrer"&gt;Solana SDK&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.thirdweb.com/guides/getting-started-with-solana/" rel="noopener noreferrer"&gt;Getting Started with Solana&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's get started!&lt;/p&gt;

&lt;h3&gt;
  
  
  Why use web3 sign-in?
&lt;/h3&gt;

&lt;p&gt;Sign-in with Solana allows you to securely log in using a wallet and verify the wallet on the backend! We are going to use Thirdweb Auth which uses the very popular JWT standard! JSON Web Token (JWT) is an open standard that defines a compact and self-contained way for securely transmitting information between parties as a JSON object.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Creating Next.js App
&lt;/h3&gt;

&lt;p&gt;I am going to use the &lt;a href="https://github.com/thirdweb-example/next-typescript-solana-starter" rel="noopener noreferrer"&gt;Next typescript solana starter template&lt;/a&gt; for this guide.&lt;/p&gt;

&lt;p&gt;If you are following along with the guide, you can create a project with the&lt;br&gt;
&lt;a href="https://github.com/thirdweb-example/next-typescript-starter" rel="noopener noreferrer"&gt;Next TypeScript template&lt;/a&gt; using the &lt;a href="https://portal.thirdweb.com/cli" rel="noopener noreferrer"&gt;thirdweb CLI&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx thirdweb create --template next-typescript-solana-starter
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you already have a Next.js app you can simply follow these steps to get started:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install the thirdweb sdks: &lt;code&gt;@thirdweb-dev/react&lt;/code&gt; and &lt;code&gt;@thirdweb-dev/sdk&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Install packages for solana wallet adapter: &lt;code&gt;@solana/wallet-adapter-react&lt;/code&gt;, &lt;code&gt;@solana/wallet-adapter-react-ui&lt;/code&gt; and &lt;code&gt;@solana/wallet-adapter-wallets&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Wrap the &lt;a href="https://github.com/thirdweb-example/next-typescript-solana-starter/blob/main/pages/_app.tsx" rel="noopener noreferrer"&gt;app&lt;/a&gt; in the &lt;code&gt;ThirdwebProvider&lt;/code&gt; and &lt;code&gt;WalletModalProvider&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Setting up thirdweb auth
&lt;/h3&gt;

&lt;p&gt;Firstly, we need to install the thirdweb auth package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i @thirdweb-dev/auth # npm

yarn add @thirdweb-dev/auth # yarn
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, create a file called &lt;code&gt;auth.config.ts&lt;/code&gt; and 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;import { ThirdwebAuth } from "@thirdweb-dev/auth/next";

export const { ThirdwebAuthHandler, getUser } = ThirdwebAuth({
  privateKey: process.env.PRIVATE_KEY as string,
  domain: "example.org",
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Update the domain with your domain.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We need the private key of our wallet. So, go to your phantom wallet (if you haven't already created one, check out &lt;a href="https://blog.thirdweb.com/guides/getting-started-with-solana" rel="noopener noreferrer"&gt;this guide&lt;/a&gt;) and click on the top right badge and select your wallet. Then click on the export private key button:&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1665622606918%2FXihvLKPfE.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1665622606918%2FXihvLKPfE.png" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Copy this private key, and paste it into a new file .env in the following format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PRIVATE_KEY=&amp;lt;your-private-key&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using private keys as an env variable is vulnerable to attacks and is not the best practice. We are doing it in this guide for the sake of brevity, but we strongly recommend using a &lt;a href="https://portal.thirdweb.com/sdk/set-up-the-sdk/securing-your-private-key" rel="noopener noreferrer"&gt;secret manager to store your private key&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To configure the auth api, create a new folder inside &lt;code&gt;pages/api&lt;/code&gt; called auth and &lt;code&gt;[...thirdweb].ts&lt;/code&gt; file inside it! Here we need to export the thirdwebHandler that we created!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { ThirdwebAuth } from "@thirdweb-dev/auth/next/solana";

export const { ThirdwebAuthHandler, getUser } = ThirdwebAuth({
  privateKey: process.env.PRIVATE_KEY as string,
  domain: "example.org",
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, inside the &lt;code&gt;_app.tsx&lt;/code&gt; file, add the authConfig prop to &lt;code&gt;ThirdwebProvider&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;  &amp;lt;ThirdwebProvider
      network={network}
      authConfig={{
        authUrl: "/api/auth",
        domain: "example.org",
        loginRedirect: "/",
      }}
    &amp;gt;
      &amp;lt;WalletModalProvider&amp;gt;
        &amp;lt;Component {...pageProps} /&amp;gt;
      &amp;lt;/WalletModalProvider&amp;gt;
    &amp;lt;/ThirdwebProvider&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Building the frontend
&lt;/h2&gt;

&lt;p&gt;Inside &lt;code&gt;pages/index.tsx&lt;/code&gt; update the return statement 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;return (
  &amp;lt;div&amp;gt;
    {publicKey ? (
      &amp;lt;button onClick={() =&amp;gt; login()}&amp;gt;Sign in with Solana&amp;lt;/button&amp;gt;
    ) : (
      &amp;lt;WalletMultiButton /&amp;gt;
    )}
  &amp;lt;/div&amp;gt;
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are going to use the &lt;code&gt;useWallet&lt;/code&gt; and &lt;code&gt;useLogin&lt;/code&gt; hooks to get the login function and user address:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const { publicKey } = useWallet();
const login = useLogin();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need to import these hooks 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;import { useWallet } from "@solana/wallet-adapter-react";
import { useLogin, useUser } from "@thirdweb-dev/react/solana";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will add sign-in with Solana to our site! Now we need to check if a user exists, so for that get the user from the &lt;code&gt;useUser&lt;/code&gt; hook 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;const { user } = useUser();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we will check if the user exists and if it exists we will return this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (user) {
  return (
    &amp;lt;div className={styles.container}&amp;gt;
      &amp;lt;p&amp;gt;You are signed in as {user.address}&amp;lt;/p&amp;gt;
      &amp;lt;button onClick={validateUser}&amp;gt;Validate user&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating api for validation
&lt;/h2&gt;

&lt;p&gt;Let's now create an api to get the user details (address) on the backend! So, create a new file called &lt;code&gt;validate.ts&lt;/code&gt; inside &lt;code&gt;pages/api&lt;/code&gt; and add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NextApiRequest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;NextApiResponse&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;next&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getUser&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../../auth.config&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NextApiRequest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NextApiResponse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;thirdwebUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;thirdwebUser&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`You are signed in as &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;thirdwebUser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;401&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Account not validated&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;405&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Method not allowed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we are using the getUser method from thirdweb to get the user's address and if it exists we send a message that "you are signed in as address".&lt;/p&gt;

&lt;h2&gt;
  
  
  Calling the API on frontend
&lt;/h2&gt;

&lt;p&gt;Create a new function called &lt;code&gt;validateUser&lt;/code&gt; in &lt;code&gt;pages/index.tsx&lt;/code&gt; 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;const validateUser = async () =&amp;gt; {
  try {
    const response = await fetch("/api/validate", {
      method: "POST",
    });

    const data = await response.json();
    alert(data.message);
  } catch (error) {
    console.log(error);
  }
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And attach this function to onClick of the validate button:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;button onClick={validateUser}&amp;gt;Validate user&amp;lt;/button&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this guide, we learned how to use thirdweb auth to add sign in with solana. Share your amazing Dapps that you built using sign in with solana on the &lt;a href="https://discord.gg/thirdweb" rel="noopener noreferrer"&gt;thirdweb discord&lt;/a&gt;! If you want to take a look at the code, check out the &lt;a href="https://github.com/thirdweb-example/sign-in-with-solana" rel="noopener noreferrer"&gt;GitHub Repository&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>solana</category>
      <category>web3</category>
      <category>thirdweb</category>
      <category>auth</category>
    </item>
    <item>
      <title>Build A Mutant Ape Yacht Club (MAYC) NFT Collection Clone</title>
      <dc:creator>Avneesh Agarwal</dc:creator>
      <pubDate>Thu, 22 Sep 2022 22:58:12 +0000</pubDate>
      <link>https://forem.com/thirdweb/build-a-mutant-ape-yacht-club-mayc-nft-collection-clone-4c61</link>
      <guid>https://forem.com/thirdweb/build-a-mutant-ape-yacht-club-mayc-nft-collection-clone-4c61</guid>
      <description>&lt;p&gt;In this guide, we'll show you how to create a clone of the MAYC collection drop where users from an original collection will be airdropped serums that can be used to mint a MAYC NFT. When the user claims the NFT, the serum will be burned.&lt;/p&gt;

&lt;p&gt;Before we get started, below are some helpful resources where you can learn more about the tools we will use in this guide.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/thirdweb-example/burn1155-mint721" rel="noopener noreferrer"&gt;View project source code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://portal.thirdweb.com/deploy" rel="noopener noreferrer"&gt;Deploy&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's get started!&lt;/p&gt;

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

&lt;p&gt;To build the smart contract we will be using Hardhat.&lt;/p&gt;

&lt;p&gt;Hardhat is an Ethereum development environment and framework designed for full stack development in Solidity. Simply put, you can write your smart contract, deploy it, run tests, and debug your code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting up a new hardhat project
&lt;/h3&gt;

&lt;p&gt;Create a folder where the hardhat project and the Next.js app will go. To create a folder, open up your terminal and execute these commands&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;mayc-clone
&lt;span class="nb"&gt;cd &lt;/span&gt;mayc-clone
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we will use the thirdweb CLI to generate a new hardhat project! So, run this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx thirdweb create --contract
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When it asks what type of project, you must select an empty one!&lt;/p&gt;

&lt;p&gt;Now you have a hardhat project ready to go!&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting up the frontend
&lt;/h3&gt;

&lt;p&gt;I am going to use the &lt;a href="https://github.com/thirdweb-example/next-typescript-starter" rel="noopener noreferrer"&gt;Next.js Typescript starter template&lt;/a&gt; for this guide.&lt;/p&gt;

&lt;p&gt;If you are following along with the guide, you can create a project with the template using the &lt;a href="https://github.com/thirdweb-dev/js/tree/main/packages/cli" rel="noopener noreferrer"&gt;thirdweb CLI&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx thirdweb create --next --ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you already have a Next.js app you can simply follow these steps to get started:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Install &lt;code&gt;@thirdweb-dev/react&lt;/code&gt; and &lt;code&gt;@thirdweb-dev/sdk&lt;/code&gt; and &lt;code&gt;ethers&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add MetaMask authentication to the site. You can follow this &lt;a href="https://portal.thirdweb.com/guides/add-connectwallet-to-your-website" rel="noopener noreferrer"&gt;guide&lt;/a&gt; to add metamask auth.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Creating the Smart Contracts
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Writing the smart contracts
&lt;/h3&gt;

&lt;h4&gt;
  
  
  BAYClone.sol
&lt;/h4&gt;

&lt;p&gt;We will now write our smart contracts! Create a new file &lt;code&gt;BAYClone.sol&lt;/code&gt; in the &lt;code&gt;contracts&lt;/code&gt; folder. We are going to use the thirdweb contracts extend feature to create a new NFT drop. So, paste the following into it&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;

import "@thirdweb-dev/contracts/base/ERC721Drop.sol";

contract BAYClone is ERC721Drop {
    constructor(
        string memory _name,
        string memory _symbol,
        address _royaltyRecipient,
        uint128 _royaltyBps,
        address _primarySaleRecipient
    )
        ERC721Drop(
            _name,
            _symbol,
            _royaltyRecipient,
            _royaltyBps,
            _primarySaleRecipient
        )
    {}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we are importing the &lt;code&gt;ERC721Drop&lt;/code&gt; contract from the thirdweb contracts package. This contract is a base contract that allows us to create a new NFT drop. We are also passing in the name, symbol, royalty recipient, royalty bps, and primary sale recipient to the constructor.&lt;/p&gt;

&lt;h4&gt;
  
  
  SerumClone.sol
&lt;/h4&gt;

&lt;p&gt;Next, we will create a new contract that will be the collection of the serum. This will be an ERC1155 contract. Create a new file &lt;code&gt;SerumClone.sol&lt;/code&gt; in the &lt;code&gt;contracts&lt;/code&gt; folder. We will also use the thirdweb contracts extend feature to create a new ERC1155 collection. So, paste the following into it&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@thirdweb-dev/contracts/base/ERC1155Base.sol";

contract SerumClone is ERC1155Base {
    constructor(
        string memory _name,
        string memory _symbol,
        address _royaltyRecipient,
        uint128 _royaltyBps
    ) ERC1155Base(_name, _symbol, _royaltyRecipient, _royaltyBps) {}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, just like the BAYC Clone, we are extending a base contract from the thirdweb contracts package. This time, we are extending the &lt;code&gt;ERC1155Base&lt;/code&gt; contract. We are also passing in the name, symbol, royalty recipient, and royalty bps to the constructor.&lt;/p&gt;

&lt;h4&gt;
  
  
  MAYClone.sol
&lt;/h4&gt;

&lt;p&gt;Finally, we will write our MAYC Clone, the most important contract. Here we are going to extend the ERC721Drop contract and add some extra functionality. Create a new file &lt;code&gt;MAYClone.sol&lt;/code&gt; in the &lt;code&gt;contracts&lt;/code&gt; folder. Paste the following into it&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;

import "@thirdweb-dev/contracts/base/ERC721LazyMint.sol";
import "@thirdweb-dev/contracts/base/ERC1155Base.sol";
import "@thirdweb-dev/contracts/base/ERC721Drop.sol";

contract MAYClone is ERC721LazyMint {
    // Store constant values for the 2 NFT Collections:
    // 1. Is the BAYC NFT Collection
    ERC721LazyMint public immutable bayc;
    // 2. Is the Serum NFT Collection
    ERC1155Base public immutable serum;

    constructor(
        string memory _name,
        string memory _symbol,
        address _royaltyRecipient,
        uint128 _royaltyBps,
        address _baycAddress,
        address _serumAddress
    ) ERC721LazyMint(_name, _symbol, _royaltyRecipient, _royaltyBps) {
        bayc = ERC721LazyMint(_baycAddress);
        serum = ERC1155Base(_serumAddress);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we are extending the &lt;code&gt;ERC721LazyMint&lt;/code&gt; contract. We are also taking in the BAYC and Serum contract addresses as constructor arguments. Now, let's add the extra functions to the contract!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; function verifyClaim(address _claimer, uint256 _quantity)
        public
        view
        virtual
        override
    {
        // 1. Override the claim function to ensure a few things:
        // - They own an NFT from the BAYClone contract
        require(bayc.balanceOf(_claimer) &amp;gt;= _quantity, "You don't own enough BAYC NFTs");
        // - They own an NFT from the SerumClone contract
        require(serum.balanceOf(_claimer, 0) &amp;gt;= _quantity, "You don't own enough Serum NFTs");
    }

    function transferTokensOnClaim(address _receiver, uint256 _quantity) internal override returns(uint256) {
        serum.burn(
            _receiver,
            0,
            _quantity
        );

        // Use the rest of the inherited claim function logic
      return super.transferTokensOnClaim(_receiver, _quantity);
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The verifyClaim function checks if the user owns enough BAYC and Serum NFTs. The transferTokensOnClaim function burns the Serum NFTs from the user and then calls the inherited transferTokensOnClaim function.&lt;/p&gt;

&lt;p&gt;Now that we have written our smart contracts, we will go ahead and deploy our contract using &lt;a href="https://portal.thirdweb.com/deploy" rel="noopener noreferrer"&gt;deploy&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deploying the contracts
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx thirdweb deploy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command allows you to avoid the painful process of setting up your entire project like setting up RPC URLs, exporting private keys, and writing scripts. Now, you will get options to choose which contract to deploy. We need to deploy all three of them so we will deploy them one by one.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1663642971252%2F3pl_H4Sj8.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1663642971252%2F3pl_H4Sj8.png" alt="Deploy"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  BAYClone
&lt;/h4&gt;

&lt;p&gt;First, let's deploy the BAYC Clone contract. Choose the BAYC Clone contract after filling out the form with your values. Deploy the contract!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1663643170328%2F03vRMkX8S.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1663643170328%2F03vRMkX8S.png" alt="BAYC"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, choose the network you want to deploy your contract to! I am going to use Goerli but you can use whichever one you like. Once you have selected your network click on &lt;code&gt;Deploy now!&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;After the transactions are mined you will be taken to the dashboard which consists of many options. Feel free to explorer them but for now we will move on with other contracts!&lt;/p&gt;

&lt;h4&gt;
  
  
  SerumClone
&lt;/h4&gt;

&lt;p&gt;Now, deploy the SerumContract in the same way as you did for the BAYC Clone contract.&lt;/p&gt;

&lt;h4&gt;
  
  
  MAYClone
&lt;/h4&gt;

&lt;p&gt;Finally, deploy the MAYC Clone contract. The deployment process will be the same as the BAYC clone and Serum Clone but you need to pass in these two addresses as well!&lt;/p&gt;

&lt;h2&gt;
  
  
  Minting NFTs from BAYC Clone
&lt;/h2&gt;

&lt;p&gt;We need to set up a claim phase so that people can claim our NFTs. We will claim one ourselves for testing as well. Go to the Claim Conditions and create a new claim phase with the parameters that you need!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1663643639337%2Fq_Q0wVym9.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1663643639337%2Fq_Q0wVym9.png" alt="Claim Conditions"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, go to the NFTs tab. Let's batch upload some NFTs for the users to mint. For this guide, I am going to use the &lt;a href="https://github.com/saminacodes/tw-demo-assets/tree/main/Shapes" rel="noopener noreferrer"&gt;Shapes batch upload example&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Click on batch upload and upload the images and the CSV/JSON file.&lt;/p&gt;

&lt;p&gt;Once they are uploaded you will be able to see the NFTs! To learn more about batch upload check out &lt;a href="https://portal.thirdweb.com/guides/how-to-batch-upload" rel="noopener noreferrer"&gt;this guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now, we need to claim some NFTs to test out the process. Go to the explorer tab and click on the claim option. Now, fill out the data I am using the following values:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;_receiver: 0x477856f90EdE4D4669f222889947bE5EE43424Db&lt;/li&gt;
&lt;li&gt;_quantity: 2&lt;/li&gt;
&lt;li&gt;_currency: 0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee&lt;/li&gt;
&lt;li&gt;_pricePerToken: 0&lt;/li&gt;
&lt;li&gt;_allowlistProof: { "proof": ["0x0000000000000000000000000000000000000000000000000000000000000000"], "maxQuantityInAllowlist": 0 }&lt;/li&gt;
&lt;li&gt;_data: []&lt;/li&gt;
&lt;li&gt;Native Token Value: 0&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1663644080632%2FC5L7wIB9T.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1663644080632%2FC5L7wIB9T.png" alt="Claim NFT"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click execute and confirm the transaction. Now, you can see that the NFTs have been claimed!&lt;/p&gt;

&lt;h2&gt;
  
  
  Airdropping NFTs from MAYC Clone
&lt;/h2&gt;

&lt;p&gt;We need to add an erc 1155 token that will be airdropped to the owners of the BAYC collection, so go to the NFTs tab and click on mint. Fill out the details and click Mint!&lt;/p&gt;

&lt;p&gt;To airdrop the serums we will create a script that will get all the owners of the BAYC NFTs and create a CSV file from it. Then we will use this CSV file to airdrop the serums. So, in our &lt;code&gt;application&lt;/code&gt; folder, create a new file called &lt;code&gt;scripts/getAll.mjs&lt;/code&gt; and add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ThirdwebSDK&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@thirdweb-dev/sdk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sdk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ThirdwebSDK&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;goerli&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;contract&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;sdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getContract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0x3714e40A15Deffb8E43A58b018bD81C2c6AC2445&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;contract&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nfts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;contract&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;nft&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;nfts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;csv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;nfts&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;nft&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;nft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;quantity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nx"&gt;quantity&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{});&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;filteredCsv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;csv&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0x0000000000000000000000000000000000000000&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nx"&gt;csv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{});&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;csvString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;address,quantity &lt;/span&gt;&lt;span class="se"&gt;\r&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
    &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filteredCsv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(([&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\r&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;nfts.csv&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;csvString&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Generated nfts.csv&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;})();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Update your contract address, and run the script. You will see a new &lt;code&gt;nfts.csv&lt;/code&gt; file 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;address,quantity
0xb371d1C5629C70ACd726B20a045D197c256E1054,1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you are done updating/checking your CSV file, go back to the dashboard and click on your NFT. Go to the airdrop tab and upload your addresses. Once done, click deploy and the serums will be airdropped to the addresses!&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding NFTs to MAYC Clone
&lt;/h2&gt;

&lt;p&gt;Just like we added NFTs to the BAYC Clone, we need to add the NFTs to MAYC clone as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building the frontend
&lt;/h2&gt;

&lt;p&gt;Now, let's build our frontend so that people can claim the MAYC NFTs! To keep our code clean we will store the mayc and serum addresses as a variable in &lt;code&gt;const/contractAddresses.ts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MAYC_ADDRESS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0xE0e3fd6782a3b87aB1bab5d78CDAF75cB453BCbe&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;SERUM_ADDRESS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0xDAcd1CDB5A144fC6fa3c55F290be778Ca47C5187&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, in &lt;code&gt;pages/index.tsx&lt;/code&gt; we will use the &lt;code&gt;Web3Button&lt;/code&gt; component to allow users to claim the NFT:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Web3Button&lt;/span&gt;
      &lt;span class="nx"&gt;contractAddress&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;MAYC_ADDRESS&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{(&lt;/span&gt;&lt;span class="nx"&gt;contract&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;mintMutantNft&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;contract&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nx"&gt;Mint&lt;/span&gt; &lt;span class="nx"&gt;Your&lt;/span&gt; &lt;span class="nx"&gt;Mutant&lt;/span&gt; &lt;span class="nx"&gt;NFT&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Web3Button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The MAYC_ADDRESS will be imported from our contractAddresses file. And as you can see we also have a function called &lt;code&gt;mintMutantNft&lt;/code&gt; so let's create that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mintMutantNft&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;maycContract&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SmartContract&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;BaseContract&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// 1. Check the approval of the mayc contract to burn the user's serum tokens&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hasApproval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;serumContract&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;isApprovedForAll&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;maycContract&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;getAddress&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;serumContract&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;balanceOf&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;hasApproval&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Set approval&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;serumContract&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;setApprovalForAll&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;maycContract&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;getAddress&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Not enough serum tokens&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;maycContract&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;claim&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we are getting the serumContract and asking for approval first as the contract needs to burn the serum. To get the address and maycContract we will use some hooks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useAddress&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;contract&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;serumContract&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useContract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;SERUM_ADDRESS&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, if we test out our app everything works! 🥳&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this guide, we learnt how to use the bases extensions to create a MAYC clone. If you built the Dapp pat yourself on the back and share it with us on the &lt;a href="https://discord.gg/thirdweb" rel="noopener noreferrer"&gt;thirdweb discord&lt;/a&gt;! If you want to take a look at the code, check out the &lt;a href="https://github.com/thirdweb-example/burn1155-mint721" rel="noopener noreferrer"&gt;GitHub Repository&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>thirdweb</category>
      <category>web3</category>
      <category>nextjs</category>
      <category>solidity</category>
    </item>
    <item>
      <title>Create a todo app with thirdweb deploy and Next.js</title>
      <dc:creator>Avneesh Agarwal</dc:creator>
      <pubDate>Mon, 12 Sep 2022 05:29:14 +0000</pubDate>
      <link>https://forem.com/thirdweb/create-a-todo-app-with-thirdweb-deploy-and-nextjs-49l3</link>
      <guid>https://forem.com/thirdweb/create-a-todo-app-with-thirdweb-deploy-and-nextjs-49l3</guid>
      <description>&lt;p&gt;This guide will show you how to build a full web3 application that allows users to create an on-chain to-do list, using Solidity for the smart contract and Next.js for the application.&lt;/p&gt;

&lt;p&gt;Before we get started, below are some helpful resources where you can learn more about the tools we're going to be using in this guide.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://github.com/thirdweb-example/todo-list"&gt;Full project source code&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://portal.thirdweb.com/release"&gt;Release&lt;/a&gt; &amp;amp; &lt;a href="https://portal.thirdweb.com/deploy"&gt;Deploy&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's get started!&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating the Smart Contract
&lt;/h2&gt;

&lt;p&gt;To build the smart contract we will be using Hardhat.&lt;/p&gt;

&lt;p&gt;Hardhat is an Ethereum development environment and framework designed for full stack development in Solidity. Simply put, you can write your smart contract, deploy it, run tests, and debug your code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting up a new hardhat project
&lt;/h3&gt;

&lt;p&gt;Create a folder where the hardhat project and the Next.js app will go. To create a folder, open up your terminal and execute these commands&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;todo-dapp
&lt;span class="nb"&gt;cd &lt;/span&gt;todo-dapp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we will use the thirdweb CLI to generate a new hardhat project! So, run this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx thirdweb create --contract
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When it asks for what type of project, you need to select an empty project!&lt;/p&gt;

&lt;p&gt;Now you have a hardhat project ready to go!&lt;/p&gt;

&lt;h3&gt;
  
  
  Writing the smart contract
&lt;/h3&gt;

&lt;p&gt;Once the app is created, create a new file inside the contracts directory called &lt;code&gt;Todo.sol&lt;/code&gt; and add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SPDX-License-Identifier: MIT

// specify the solidity version here
pragma solidity ^0.8.0;

contract Todos {
    // We will declare an array of strings called todos
    string[] public todos;

    // We will take _todo as input and push it inside the array in this function
    function setTodo(string memory _todo) public {
        todos.push(_todo);
    }

    // In this function we are just returning the array
    function getTodo() public view returns (string[] memory) {
        return todos;
    }

    // Here we are returning the length of the todos array
    function getTodosLength() public view returns (uint) {
        uint todosLength = todos.length;
        return todosLength;
    }

    // We are using the pop method to remove a todo from the array as you can see we are just removing one index
    function deleteToDo(uint _index) public {
        require(_index &amp;lt; todos.length, "This todo index does not exist.");
        todos[_index] = todos[getTodosLength() - 1];
        todos.pop();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This smart contract allows you to add todos to your contract, remove them, get their length and return the array which consists of all the tasks you have set up.&lt;/p&gt;

&lt;p&gt;Now that we have written our basic &lt;code&gt;Todos&lt;/code&gt; smart contract, we will go ahead and deploy our contract using &lt;a href="https://portal.thirdweb.com/deploy"&gt;deploy&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deploying the contract
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx thirdweb deploy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command allows you to avoid the painful process of setting up your entire project like setting up RPC URLs, exporting private keys, and writing scripts.&lt;/p&gt;

&lt;p&gt;Upon success, a new tab will automatically open and you should be able to see a link to the dashboard in your CLI.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fgV_xcPx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1662950728342/gyi2Ncb6E.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fgV_xcPx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1662950728342/gyi2Ncb6E.png" alt="image.png" width="880" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, choose the network you want to deploy your contract to! I am going to use Goerli but you can use whichever one you like. Once you have chosen your network click on &lt;code&gt;Deploy now!&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5a5d9t14--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1662950749737/MnEbNy4e9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5a5d9t14--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1662950749737/MnEbNy4e9.png" alt="image.png" width="880" height="337"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After the transactions are mined you will be taken to the dashboard which consists of many options.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  In the &lt;strong&gt;overview&lt;/strong&gt; section, you can explore your contract and interact with the functions without having to integrate them within your frontend code yet so it gives you a better idea of how your functions are working and also acts as a good testing environment.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wuWD1eNX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1662950763730/N7VfzapNu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wuWD1eNX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1662950763730/N7VfzapNu.png" alt="image.png" width="880" height="455"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  In the &lt;strong&gt;code&lt;/strong&gt; section, you see the different languages and ways you can interact with your contract. Which we will look into later on in the tutorial.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--N8bw7PFH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1662950773074/p8tPFb8IL.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--N8bw7PFH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1662950773074/p8tPFb8IL.png" alt="image.png" width="880" height="458"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  In the &lt;strong&gt;events&lt;/strong&gt; section, you can see all the transactions you make.&lt;/li&gt;
&lt;li&gt;  You can also customize the *&lt;strong&gt;&lt;em&gt;settings&lt;/em&gt;&lt;/strong&gt;* after enabling the required interfaces in the settings section.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--x8uDCswL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1662950781456/P7KkWsUJW.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--x8uDCswL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1662950781456/P7KkWsUJW.png" alt="image.png" width="880" height="386"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  In the &lt;strong&gt;source&lt;/strong&gt; section, you can see your smart contract and it also gives you a verification button to the relevant chain to which you have deployed your contract.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5K4VxTak--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1662950801089/--qY0EUby.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5K4VxTak--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1662950801089/--qY0EUby.png" alt="image.png" width="880" height="490"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating the Frontend
&lt;/h2&gt;

&lt;p&gt;I am going to use the &lt;a href="https://github.com/thirdweb-example/next-typescript-starter"&gt;Next.js Typescript starter template&lt;/a&gt; for this guide.&lt;/p&gt;

&lt;p&gt;If you are following along with the guide, you can create a project with the template using the &lt;a href=""&gt;thirdweb CLI&lt;/a&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx thirdweb create --next --ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;If you already have a Next.js app you can simply follow these steps to get started:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Install &lt;code&gt;@thirdweb-dev/react&lt;/code&gt; and &lt;code&gt;@thirdweb-dev/sdk&lt;/code&gt; and &lt;code&gt;ethers&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  Add MetaMask authentication to the site. You can follow this &lt;a href=""&gt;guide&lt;/a&gt; to do this.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By default the network is Mainnet, we need to change it to Goerli&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import type { AppProps } from "next/app";
import { ChainId, ThirdwebProvider } from "@thirdweb-dev/react";

// This is the chainId your dApp will work on.
const activeChainId = ChainId.Goerli;

function MyApp({ Component, pageProps }: AppProps) {
  return (
    &amp;lt;ThirdwebProvider desiredChainId={activeChainId}&amp;gt;
      &amp;lt;Component {...pageProps} /&amp;gt;
    &amp;lt;/ThirdwebProvider&amp;gt;
  );
}

export default MyApp;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create todo functionality
&lt;/h3&gt;

&lt;p&gt;Let's now go to &lt;code&gt;pages/index.tsx&lt;/code&gt; and firstly, get the wallet address of the user 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;const address = useAddress();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, we are going to check if the address exists and if it does we are going to show a simple input and button to create a new todo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div&amp;gt;
  {address ? (
    &amp;lt;div&amp;gt;
      &amp;lt;input
        value={input}
        onChange={(e) =&amp;gt; setInput(e.target.value)}
        placeholder="Enter todo"
      /&amp;gt;

      &amp;lt;Web3Button
        contractAddress={contractAddress}
        action={(contract) =&amp;gt; contract.call("setTodo", input)}
      &amp;gt;
        Set Todo
      &amp;lt;/Web3Button&amp;gt;
    &amp;lt;/div&amp;gt;
  ) : (
    &amp;lt;ConnectWallet  /&amp;gt;
  )}
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are using a state to store the value of a state variable and I have also created a variable for &lt;code&gt;contractAddress&lt;/code&gt; as it will be used in multiple places:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  const contractAddress = "0x80ddA9989F272BFB1c53c1A100ff118Fd27dDb59";
  const [input, setInput] = useState("");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To get the contract address go to your contract on thirdweb and copy the contract&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lvCqQfAH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1662950890293/G6rOmEoXB.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lvCqQfAH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1662950890293/G6rOmEoXB.png" alt="image.png" width="606" height="176"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you now check out the app, you will be able to add todos!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yNhZoqrT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1662950896804/QrLid3xt-.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yNhZoqrT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1662950896804/QrLid3xt-.png" alt="image.png" width="880" height="550"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Read todos functionality
&lt;/h3&gt;

&lt;p&gt;Using the &lt;code&gt;useContract&lt;/code&gt; and &lt;code&gt;useContractData&lt;/code&gt; hooks we will get the todos 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;const { contract } = useContract(contractAddress);
const { data, isLoading } = useContractData(contract, "getTodo");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we will check if the todos are loading and if it is loading we will show a loading screen otherwise we will show the todos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  &amp;lt;div&amp;gt;
            {isLoading ? (
              "Loading..."
            ) : (
              &amp;lt;ul&amp;gt;
                {data.map((item: string, index: number) =&amp;gt; (
                  &amp;lt;li key={index}&amp;gt;
                    {item}
                  &amp;lt;/li&amp;gt;
                ))}
              &amp;lt;/ul&amp;gt;
            )}
          &amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will now be able to see all the todos 🎉&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Sax6ztdB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1662950933100/wm7PBSweX.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Sax6ztdB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1662950933100/wm7PBSweX.png" alt="image.png" width="880" height="516"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding delete functionality
&lt;/h3&gt;

&lt;p&gt;Where we are mapping through all the todos we will add another &lt;code&gt;Web3Button&lt;/code&gt; that will be responsible for deleting the todos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; {data.map((item: string, index: number) =&amp;gt; (
                  &amp;lt;li key={index}&amp;gt;
                    {item}
                    &amp;lt;Web3Button
                      contractAddress={contractAddress}
                      action={(contract) =&amp;gt; contract.call("deleteToDo", index)}
                    &amp;gt;
                      Delete Todo
                    &amp;lt;/Web3Button&amp;gt;
                  &amp;lt;/li&amp;gt;
                ))}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Adding some styles
&lt;/h3&gt;

&lt;p&gt;We will add some basic styles to our app so it looks good! So, create a &lt;code&gt;globals.css&lt;/code&gt; file in the &lt;code&gt;styles&lt;/code&gt; folder and add 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;html,
body {
  padding: 0;
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu,
    Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
}

a {
  color: inherit;
  text-decoration: none;
}

* {
  box-sizing: border-box;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, import it in &lt;code&gt;_app.tsx&lt;/code&gt; 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;import "../styles/globals.css";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's style the home page now! Create a file &lt;code&gt;Home.module.css&lt;/code&gt; and add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;flex&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;direction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;column&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;align&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;justify&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="nx"&gt;vw&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;min&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="nx"&gt;vh&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;background&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;c0ffee&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;align&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;justify&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;space&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;between&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;gap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="nx"&gt;px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;margin&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="nx"&gt;px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;span&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="nx"&gt;px&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;todoForm&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;align&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;justify&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;space&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;between&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;margin&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="nx"&gt;px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;gap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="nx"&gt;px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;todoForm&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;span&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="nx"&gt;px&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, add the classNames:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import {
  ConnectWallet,
  useAddress,
  useContract,
  useContractData,
  Web3Button,
} from "@thirdweb-dev/react";
import type { NextPage } from "next";
import { useState } from "react";
import styles from "../styles/Home.module.css";

const Home: NextPage = () =&amp;gt; {
  const address = useAddress();
  const contractAddress = "0x80ddA9989F272BFB1c53c1A100ff118Fd27dDb59";
  const [input, setInput] = useState("");
  const { contract } = useContract(contractAddress);
  const { data, isLoading } = useContractData(contract, "getTodo");

  return (
    &amp;lt;div className={styles.container}&amp;gt;
      {address ? (
        &amp;lt;&amp;gt;
          &amp;lt;div className={styles.todoForm}&amp;gt;
            &amp;lt;input
              value={input}
              onChange={(e) =&amp;gt; setInput(e.target.value)}
              placeholder="Enter todo"
            /&amp;gt;

            &amp;lt;Web3Button
              contractAddress={contractAddress}
              action={(contract) =&amp;gt; contract.call("setTodo", input)}
              accentColor="#1ce"
            &amp;gt;
              Set Todo
            &amp;lt;/Web3Button&amp;gt;
          &amp;lt;/div&amp;gt;

          &amp;lt;div&amp;gt;
            {isLoading ? (
              "Loading..."
            ) : (
              &amp;lt;ul&amp;gt;
                {data.map((item: string, index: number) =&amp;gt; (
                  &amp;lt;li key={index} className={styles.todo}&amp;gt;
                    {item}
                    &amp;lt;Web3Button
                      contractAddress={contractAddress}
                      action={(contract) =&amp;gt; contract.call("deleteToDo", index)}
                      accentColor="#1ce"
                    &amp;gt;
                      Delete Todo
                    &amp;lt;/Web3Button&amp;gt;
                  &amp;lt;/li&amp;gt;
                ))}
              &amp;lt;/ul&amp;gt;
            )}
          &amp;lt;/div&amp;gt;
        &amp;lt;/&amp;gt;
      ) : (
        &amp;lt;ConnectWallet accentColor="#1ce" colorMode="light" /&amp;gt;
      )}
    &amp;lt;/div&amp;gt;
  );
};

export default Home;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we have an awesome web3 to-do app ready! 🥳&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AslJ7yLO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1662951004312/wpiwBGroC.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AslJ7yLO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1662951004312/wpiwBGroC.png" alt="image.png" width="880" height="510"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this guide, we've learned how to build a full-stack web3 todo app! If you did as well pat yourself on the back and share it with us on the &lt;a href="https://discord.gg/thirdweb"&gt;thirdweb discord&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>thirdweb</category>
      <category>solidity</category>
      <category>web3</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>Allow GitHub contributors to mint an NFT</title>
      <dc:creator>Avneesh Agarwal</dc:creator>
      <pubDate>Mon, 12 Sep 2022 05:26:18 +0000</pubDate>
      <link>https://forem.com/thirdweb/allow-github-contributors-to-mint-an-nft-5a52</link>
      <guid>https://forem.com/thirdweb/allow-github-contributors-to-mint-an-nft-5a52</guid>
      <description>&lt;p&gt;In this guide, we'll show you how to create an app where users can sign in with their GitHub and web3 wallet. Once they are signed in, we will validate if they have contributed to one of our repos; and if they have, we will allow the users to mint an NFT using signature-based minting!&lt;/p&gt;

&lt;p&gt;Before we get started, below are some helpful resources where you can learn more about the tools we're going to be using in this guide.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/avneesh0612/github-contributor-nft-rewards"&gt;View project source code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://portal.thirdweb.com/pre-built-contracts/edition"&gt;Edition contract&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://portal.thirdweb.com/auth"&gt;Auth&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's get started!&lt;/p&gt;

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

&lt;p&gt;I am going to use the &lt;a href="https://github.com/thirdweb-example/next-typescript-starter"&gt;Next.js Typescript starter template&lt;/a&gt; for this guide.&lt;/p&gt;

&lt;p&gt;If you are following along with the guide, you can create a project with the template using the &lt;a href="https://github.com/thirdweb-dev/js/tree/main/packages/cli"&gt;thirdweb CLI&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx thirdweb create --next --ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you already have a Next.js app you can simply follow these steps to get started:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Install &lt;code&gt;@thirdweb-dev/react&lt;/code&gt; and &lt;code&gt;@thirdweb-dev/sdk&lt;/code&gt; and &lt;code&gt;ethers&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add MetaMask authentication to the site. You can follow this &lt;a href="https://portal.thirdweb.com/guides/add-connectwallet-to-your-website"&gt;guide&lt;/a&gt; to add metamask auth.&lt;br&gt;
By default the network is Mainnet, we need to change it to Goerli.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import type { AppProps } from "next/app";
import { ChainId, ThirdwebProvider } from "@thirdweb-dev/react";

// This is the chainId your dApp will work on.
const activeChainId = ChainId.Goerli;

function MyApp({ Component, pageProps }: AppProps) {
  return (
    &amp;lt;ThirdwebProvider desiredChainId={activeChainId}&amp;gt;
      &amp;lt;Component {...pageProps} /&amp;gt;
    &amp;lt;/ThirdwebProvider&amp;gt;
  );
}

export default MyApp;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Creating an Edition Contract and Lazy-Minting An NFT
&lt;/h3&gt;

&lt;p&gt;Let's go ahead and deploy an Edition contract and add an NFT!&lt;/p&gt;

&lt;p&gt;To do that, head to the &lt;a href="https://thirdweb.com/dashboard"&gt;thirdweb dashboard&lt;/a&gt; and create an Edition contract!&lt;/p&gt;

&lt;p&gt;Fill out the details and deploy the contract by clicking on &lt;code&gt;Deploy Now&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8l_DRsVT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1662951517478/RdrxdAG3g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8l_DRsVT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1662951517478/RdrxdAG3g.png" alt="image.png" width="880" height="488"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the contract is deployed, go to the NFTs tab and click on Mint. Enter the details of your NFT and set the initial supply to 0. Once you have filled out all the details, click on Mint NFT!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hJGguAMB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1662951526341/LF_4gDE4i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hJGguAMB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1662951526341/LF_4gDE4i.png" alt="image.png" width="880" height="479"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We only want users to own &lt;code&gt;1&lt;/code&gt; NFT per wallet from this collection. To achieve this, we'll set our NFTs to be &lt;strong&gt;soulbound&lt;/strong&gt;, meaning they cannot transfer it!&lt;/p&gt;

&lt;p&gt;Head to the permissions tab and set the NFTs of this collection to be Non-Transferrable.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--my-Y-MN2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1662951549923/URUTn2Rl5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--my-Y-MN2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1662951549923/URUTn2Rl5.png" alt="image.png" width="880" height="203"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up Auth
&lt;/h2&gt;

&lt;p&gt;We need the user to sign in both with their wallet and with their GitHub account, to do this, we'll first set up web3 sign-in using thirdweb then use NextAuth to add GitHub authentication!&lt;/p&gt;

&lt;h3&gt;
  
  
  thirdweb Auth
&lt;/h3&gt;

&lt;p&gt;Firstly, we need to install the thirdweb auth package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i @thirdweb-dev/auth # npm

yarn add @thirdweb-dev/auth # yarn
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, create a file called auth.config.ts and 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;import { ThirdwebAuth } from "@thirdweb-dev/auth/next";

export const { ThirdwebAuthHandler, getUser } = ThirdwebAuth({
    // Using environment variables to secure your private key is a security vulnerability.
    // Learn how to store your private key securely:
    // https://portal.thirdweb.com/sdk/set-up-the-sdk/securing-your-private-key
    process.env.ADMIN_PRIVATE_KEY!,
  // Set this to your domain to prevent signature malleability attacks.
  const domain = "http://localhost:3000";
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The domain is important since you don't want your users signing malicious signatures&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a new &lt;code&gt;.env.local&lt;/code&gt; file and add a new variable named &lt;code&gt;PRIVATE_KEY&lt;/code&gt;. Learn how to &lt;a href="https://portal.thirdweb.com/guides/create-a-metamask-wallet?utm_source=hashnode&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=on-demand-pass#export-your-private-key"&gt;export your private key&lt;/a&gt; from your wallet. Using private keys as an env variable is vulnerable to attacks and is not the best practice. We are doing it in this guide for the sake of brevity, but we strongly recommend &lt;a href="https://portal.thirdweb.com/sdk/set-up-the-sdk/securing-your-private-key"&gt;using a secret manager to store your private key&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To configure the auth API, create a new folder inside &lt;code&gt;pages/api&lt;/code&gt; called &lt;code&gt;thirdwebauth&lt;/code&gt; and a &lt;code&gt;[...thirdweb].ts&lt;/code&gt; file inside it!&lt;/p&gt;

&lt;p&gt;Within this file, we need to export the &lt;code&gt;ThirdwebHandler&lt;/code&gt; that we made in the config file previously.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { ThirdwebAuthHandler } from "../../../auth.config";

export default ThirdwebAuthHandler();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will catch all the API requests that go to &lt;code&gt;/api/auth/...&lt;/code&gt;, using Next.js's catch-all API route syntax.&lt;/p&gt;

&lt;p&gt;Behind the scenes, this handles the logic for three endpoints that we're going to utilize: &lt;code&gt;/login&lt;/code&gt;, &lt;code&gt;/logout&lt;/code&gt;, and &lt;code&gt;/user&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Finally, inside the &lt;code&gt;_app.tsx&lt;/code&gt; file, add the &lt;code&gt;authConfig&lt;/code&gt; prop to &lt;code&gt;ThirdwebProvider&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;    &amp;lt;ThirdwebProvider
      desiredChainId={activeChainId}
      authConfig={{
        authUrl: "/api/thirdwebauth",
        domain: "example.org",
        loginRedirect: "/",
      }}
    &amp;gt;
      &amp;lt;Component {...pageProps} /&amp;gt;
    &amp;lt;/ThirdwebProvider&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Next Auth with GitHub
&lt;/h3&gt;

&lt;p&gt;Create a new folder called &lt;code&gt;auth&lt;/code&gt; inside the &lt;code&gt;pages/api&lt;/code&gt; folder and then create a file inside &lt;code&gt;auth&lt;/code&gt; called &lt;code&gt;[...nextauth].ts&lt;/code&gt;. Once you have done this add the following to 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;import NextAuth, { NextAuthOptions } from "next-auth";
import GithubProvider from "next-auth/providers/github";

export const authOptions: NextAuthOptions = {
  providers: [
    GithubProvider({
      clientId: process.env.GITHUB_ID as string,
      clientSecret: process.env.GITHUB_SECRET as string,
    }),
  ],

  callbacks: {
    async session({ session, token }) {
      session.id = token.sub;
      return session;
    },
  },
};

export default NextAuth(authOptions);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, go to &lt;code&gt;_app.tsx&lt;/code&gt; and wrap the component in a session provider 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;&amp;lt;SessionProvider session={pageProps.session} refetchInterval={0}&amp;gt;
        &amp;lt;Component {...pageProps} /&amp;gt;
&amp;lt;/SessionProvider&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;SessionProvider&lt;/code&gt; will be imported from next-auth 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;import { SessionProvider } from "next-auth/react";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need to add some env variables to make the auth work! In the &lt;code&gt;.env.local&lt;/code&gt; file add these variables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GITHUB_ID=
GITHUB_SECRET=
NEXTAUTH_URL=
NEXTAUTH_SECRET=
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;NEXTAUTH_URL&lt;/code&gt; will be a link to the homepage of your website, since we are working on localhost it will be &lt;code&gt;http://localhost:3000&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To generate a secret run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;openssl rand -base64 32               
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we need to create a GitHub OAuth app. You can do that from the &lt;a href="https://github.com/settings/applications/new"&gt;Github Developer Settings&lt;/a&gt; and fill out the information like so:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--72f0s9Rw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1662951831291/TWEwr9dDp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--72f0s9Rw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1662951831291/TWEwr9dDp.png" alt="image.png" width="880" height="493"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, copy the client id and generate a new secret and copy that. Go to your &lt;code&gt;.env.local&lt;/code&gt; file and update these variables. Once you have filled all the env vars restart your dev server!&lt;/p&gt;

&lt;p&gt;Next, follow Github's &lt;a href="https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token"&gt;Creating a personal access token&lt;/a&gt; guide and add this as an environment variable in your project. We'll use this to make requests to GitHub's API without getting rate-limited.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating the login page
&lt;/h2&gt;

&lt;p&gt;Create a new file &lt;code&gt;login.tsx&lt;/code&gt; inside the &lt;code&gt;pages&lt;/code&gt; folder and add 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;import React from "react";
import { useSession, signIn } from "next-auth/react";
import styles from "../styles/Home.module.css";

const Login = () =&amp;gt; {
  const { data: session } = useSession();

  if (!session) {
    return (
      &amp;lt;div className={styles.container}&amp;gt;
        &amp;lt;button className={styles.mainButton} onClick={() =&amp;gt; signIn()}&amp;gt;
          Sign in with GitHub
        &amp;lt;/button&amp;gt;
      &amp;lt;/div&amp;gt;
    );
  }
};

export default Login;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will show a Sign in with GitHub button if there is no session detected from NextAuth.&lt;/p&gt;

&lt;p&gt;Now, we will check for the address and thirdweb user. If the user's wallet is not connected/the user isn't signed in we will show the corresponding buttons.&lt;/p&gt;

&lt;p&gt;Firstly, we are going to need 3 hooks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  const login = useLogin();
  const address = useAddress();
  const connect = useMetamask();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Below the session check add 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;  if (!address) {
    return (
      &amp;lt;div className={styles.container}&amp;gt;
        &amp;lt;button className={styles.mainButton} onClick={() =&amp;gt; connect()}&amp;gt;
          Connect Wallet
        &amp;lt;/button&amp;gt;
      &amp;lt;/div&amp;gt;
    );
  }

  return (
    &amp;lt;div className={styles.container}&amp;gt;
      &amp;lt;button className={styles.mainButton} onClick={() =&amp;gt; login()}&amp;gt;
        Sign in with Ethereum
      &amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  );
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code block will first check if there is an address present. If there is no address present it will show the &lt;code&gt;connect wallet&lt;/code&gt; button; otherwise, the &lt;code&gt;sign in with Ethereum&lt;/code&gt; button.&lt;/p&gt;

&lt;p&gt;We are using css modules to add some basic stylings to the app, so if you want to add the stylings as well. Create a new folder &lt;code&gt;styles&lt;/code&gt; and &lt;code&gt;globals.css&lt;/code&gt; inside it&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;html,
body {
  padding: 0;
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu,
    Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
}

a {
  color: inherit;
  text-decoration: none;
}

* {
  box-sizing: border-box;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, import it in _app.tsx 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;import "../styles/globals.css";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, create another file called Home.module.css and 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;.container {
  width: 100%;
  height: 70vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.mainButton {
  background: linear-gradient(to right, #ff1b6b, #45caff);
  border: none;
  color: #fff;
  font-weight: 700;
  padding: 10px 20px;
  text-align: center;
  text-decoration: none;
  display: inline-block;
  font-size: 16px;
  margin: 4px 2px;
  cursor: pointer;
  border-radius: 5px;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we have the auth flow completed! You can go to &lt;a href="http://localhost:3000/login"&gt;http://localhost:3000/login&lt;/a&gt; and check it out yourself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating the API for claim
&lt;/h2&gt;

&lt;p&gt;Create a new file &lt;code&gt;claim-nft.ts&lt;/code&gt; inside the &lt;code&gt;pages/api&lt;/code&gt; folder. We are going to need to create an api so add 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;import type { NextApiRequest, NextApiResponse } from "next";

const claimNft = async (req: NextApiRequest, res: NextApiResponse) =&amp;gt; {
  if (req.method !== "POST") {
    return res.status(405).json({ error: "Method not allowed" });
  }

  return res.status(200).json({ message: "gm" });
};

export default claimNft;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This api first checks if the request is of the post method or not and if it is using the post method we will send a message "gm".&lt;/p&gt;

&lt;p&gt;Now, let's get into the actual code! We will first get the users from the next auth and thirdweb auth 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;  const session = await unstable_getServerSession(req, res, authOptions);
  const thirdwebUser = await getUser(req);

  if (!session || !thirdwebUser) {
    return res.status(401).json({ message: "Unauthorized" });
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need to import them 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;import { unstable_getServerSession } from "next-auth/next";
import { getUser } from "../../auth.config";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These are the two functions we use to view the authenticated user's information on the server-side:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;unstable_getServerSession&lt;/code&gt; is our way of getting the connected Github account&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;getUser&lt;/code&gt; is our way of viewing the authenticated wallet.
Now, we will create a new array that will have a list of repos to check for:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const reposToCheck = [
    "js",
    "react",
    "typescript-sdk",
    "thirdweb-cli",
    "contracts",
    "auth",
    "storage",
    "go-sdk",
    "python-sdk",
    "docs",
    "portal",
    "examples",
  ];
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we have added some of our thirdweb repositories, but you need to update this with your list of repositories to check.&lt;/p&gt;

&lt;p&gt;Now, we will loop through this array and for each item we will check if the user has contributed to them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let hasContributed = false;

  for (const repo of reposToCheck) {
    const contributors: GithubContributor[] = await fetch(
      `https://api.github.com/repos/thirdweb-dev/${repo}/contributors`,
      {
        headers: {
          Authorization: `token ${process.env.GITHUB_ACCESS_TOKEN}`,
        },
      }
    ).then((res) =&amp;gt; res.json());

    const hasContributedToThisRepo = contributors?.some((contributor) =&amp;gt; {
      return contributor.id.toString() === session.id;
    });

    if (hasContributedToThisRepo) {
      hasContributed = true;
    }
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we know if the user has contributed or not, if the user has not contributed we will simply say that you don't qualify:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  if (!hasContributed) {
    return res.status(401).json({ message: "Sorry, you don't qualify" });
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let's initialize our SDK using our private key:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; const sdk = ThirdwebSDK.fromPrivateKey(
     // Using environment variables to secure your private key is a security vulnerability.
    // Learn how to store your private key securely:
    // https://portal.thirdweb.com/sdk/set-up-the-sdk/securing-your-private-key
    process.env.PRIVATE_KEY as string,
    "goerli"
  );
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will first check if the user already owns one of our NFTs first:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  const edition = sdk.getEdition("0xD71c27e6325f018b15E16C3992654F1b089C5fCe");

  const balance = await edition.balanceOf(thirdwebUser.address, 0);

  if (balance.gt(0)) {
    return res.status(401).json({ message: "You already have an NFT" });
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we will generate the signature to mint the NFT!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  const signedPayload = await edition.signature.generateFromTokenId({
    quantity: 1,
    tokenId: 0,
    to: thirdwebUser.address,
  });

  return res.status(200).json({ signedPayload });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our final API code will looks 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;import type { NextApiRequest, NextApiResponse } from "next";
import { unstable_getServerSession } from "next-auth/next";
import { getUser } from "../../auth.config";
import GithubContributor from "../../types/GithubContributor";
import { ThirdwebSDK } from "@thirdweb-dev/sdk";
import { authOptions } from "./auth/[...nextauth]";

const claimNft = async (req: NextApiRequest, res: NextApiResponse) =&amp;gt; {
  if (req.method !== "POST") {
    return res.status(405).json({ error: "Method not allowed" });
  }

  const session = await unstable_getServerSession(req, res, authOptions);
  const thirdwebUser = await getUser(req);

  if (!session || !thirdwebUser) {
    return res.status(401).json({ message: "Unauthorized" });
  }

  const reposToCheck = [
    "js",
    "react",
    "typescript-sdk",
    "thirdweb-cli",
    "contracts",
    "auth",
    "storage",
    "go-sdk",
    "python-sdk",
    "docs",
    "portal",
    "examples",
  ];

  let hasContributed = false;

  for (const repo of reposToCheck) {
    const contributors: GithubContributor[] = await fetch(
      `https://api.github.com/repos/thirdweb-dev/${repo}/contributors`,
      {
        headers: {
          Authorization: `token ${process.env.GITHUB_ACCESS_TOKEN}`,
        },
      }
    ).then((res) =&amp;gt; res.json());

    const hasContributedToThisRepo = contributors?.some((contributor) =&amp;gt; {
      return contributor.id.toString() === session.id;
    });

    if (hasContributedToThisRepo) {
      hasContributed = true;
    }
  }

  if (!hasContributed) {
    return res.status(401).json({ message: "Sorry, you don't qualify" });
  }

  const sdk = ThirdwebSDK.fromPrivateKey(
    process.env.PRIVATE_KEY as string,
    "goerli"
  );

  const edition = sdk.getEdition("0xD71c27e6325f018b15E16C3992654F1b089C5fCe");

  const balance = await edition.balanceOf(thirdwebUser.address, 0);

  if (balance.gt(0)) {
    return res.status(401).json({ message: "You already have an NFT" });
  }

  const signedPayload = await edition.signature.generateFromTokenId({
    quantity: 1,
    tokenId: 0,
    to: thirdwebUser.address,
  });

  return res.status(200).json({ signedPayload });
};

export default claimNft;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating the frontend
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Calling the API on the frontend
&lt;/h3&gt;

&lt;p&gt;Go to &lt;code&gt;pages/index.tsx&lt;/code&gt; and update the return block:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  return (
    &amp;lt;div className={styles.container}&amp;gt;
      &amp;lt;h1&amp;gt;GitHub Contributor NFTs&amp;lt;/h1&amp;gt;
      &amp;lt;p&amp;gt;
        Claim an NFT if you have contributed to any of thirdweb&amp;amp;apos;s repos.
      &amp;lt;/p&amp;gt;

      {!address ? (
        &amp;lt;button
          className={styles.mainButton}
          disabled={loading}
          onClick={() =&amp;gt; connect()}
        &amp;gt;
          Connect to Metamask
        &amp;lt;/button&amp;gt;
      ) : (
        &amp;lt;button
          className={styles.mainButton}
          disabled={loading}
          onClick={mintNft}
        &amp;gt;
          {loading ? "Loading..." : "Claim NFT"}
        &amp;lt;/button&amp;gt;
      )}
    &amp;lt;/div&amp;gt;
  );
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are going to check if the user's wallet is connected and if it is then we will show a button to claim the NFT!&lt;/p&gt;

&lt;p&gt;As you can see we are going to need a &lt;code&gt;mintNFT&lt;/code&gt;function so let's create that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const mintNft = async () =&amp;gt; {
    setLoading(true);

    if (networkMismatch) {
      return switchNetwork?.(ChainId.Goerli);
    }

    try {
      const req = await fetch("/api/claim-nft", {
        method: "POST",
      });

      const res = await req.json();

      if (!req.ok) {
        return alert(`Error: ${res.message}`);
      }

      await edition?.signature.mint(res.signedPayload);

      alert("Successfully minted NFT 🚀");
    } catch (err) {
      console.error(err);
      alert("Failed to mint NFT");
    } finally {
      setLoading(false);
    }
  };
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are also using some hooks to access the edition contract, get the user's address, connect the wallet to MetaMask, store loading, etc.:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const edition = useEdition("0xD71c27e6325f018b15E16C3992654F1b089C5fCe");
  const connect = useMetamask();
  const address = useAddress();
  const [, switchNetwork] = useNetwork();
  const networkMismatch = useNetworkMismatch();
  const [loading, setLoading] = useState&amp;lt;boolean&amp;gt;(false);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, if you have contributed to any of the repositories you will successfully be able to mint the NFT! 🎉&lt;/p&gt;

&lt;h3&gt;
  
  
  Redirecting users if they are not logged in
&lt;/h3&gt;

&lt;p&gt;If the user is not logged in and they come to the home page we should redirect them to &lt;code&gt;/login&lt;/code&gt; so, we are going to use SSR to redirect the user if they are not logged in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export const getServerSideProps: GetServerSideProps = async (context) =&amp;gt; {
  const thirdwebUser = await getUser(context.req);

  const session = await unstable_getServerSession(
    context.req,
    context.res,
    authOptions
  );

  if (!thirdwebUser || !session) {
    return {
      redirect: {
        destination: "/login",
        permanent: false,
      },
    };
  }

  return {
    props: {},
  };
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this guide, we learnt how to use thirdweb auth to allow only users who have contributed to our repos to mint an NFT!&lt;/p&gt;

&lt;p&gt;If you did as well pat yourself on the back and share it with us on the &lt;a href="https://discord.gg/thirdweb"&gt;thirdweb discord&lt;/a&gt;! If you want to take a look at the code, check out the &lt;a href="https://github.com/thirdweb-example/github-contributor-nft-rewards"&gt;GitHub Repository&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>thirdweb</category>
      <category>nextjs</category>
      <category>auth</category>
      <category>nft</category>
    </item>
    <item>
      <title>Create on-demand access pass minting (ERC 721)</title>
      <dc:creator>Avneesh Agarwal</dc:creator>
      <pubDate>Wed, 17 Aug 2022 13:11:52 +0000</pubDate>
      <link>https://forem.com/thirdweb/create-on-demand-access-pass-minting-erc-721-3c0m</link>
      <guid>https://forem.com/thirdweb/create-on-demand-access-pass-minting-erc-721-3c0m</guid>
      <description>&lt;h2&gt;
  
  
  What is thirdweb?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://thirdweb.com/dashboard?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=on-demand-pass" rel="noopener noreferrer"&gt;thirdweb&lt;/a&gt; is a platform that lets you deploy smart contracts without having to know Solidity, you can do it by using TypeScript, Python or Go or even without writing any code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In this guide, we will create an &lt;a href="https://portal.thirdweb.com/pre-built-contracts/nft-collection?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=on-demand-pass" rel="noopener noreferrer"&gt;NFT collection&lt;/a&gt; where users can connect their wallets to the website and mint an NFT by generating a signature. The metadata of the signature will be the same for everyone but this will help us send ERC 721 tokens which are unique to all the users.&lt;/p&gt;

&lt;p&gt;This collection of passes will be similar to the &lt;a href="https://opensea.io/collection/fnatic-citizen" rel="noopener noreferrer"&gt;Fnatic passes drop&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Before we get started, below are some helpful resources where you can learn more about the tools we will use in this guide.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/thirdweb-dev/examples/tree/main/typescript/on-demand-pass" rel="noopener noreferrer"&gt;View Project Source Code&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://portal.thirdweb.com/pre-built-contracts/nft-collection?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=on-demand-pass" rel="noopener noreferrer"&gt;NFT Collection Contract&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's get started.&lt;/p&gt;

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

&lt;p&gt;I am going to use the &lt;a href="https://github.com/thirdweb-example/next-typescript-starter" rel="noopener noreferrer"&gt;Next typescript starter template&lt;/a&gt; for this guide.&lt;/p&gt;

&lt;p&gt;If you are following along with the guide, you can create a project with the&lt;br&gt;
&lt;a href="https://github.com/thirdweb-example/next-typescript-starter" rel="noopener noreferrer"&gt;Next TypeScript template&lt;/a&gt; using the &lt;a href="https://portal.thirdweb.com/cli?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=on-demand-pass" rel="noopener noreferrer"&gt;thirdweb CLI&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx thirdweb create --next --ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you already have a Next.js app you can simply follow these steps to get started:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install &lt;code&gt;@thirdweb-dev/react&lt;/code&gt; and &lt;code&gt;@thirdweb-dev/sdk&lt;/code&gt; and &lt;code&gt;ethers&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Add MetaMask authentication to the site. You can follow this &lt;a href="https://portal.thirdweb.com/guides/add-connectwallet-to-your-website?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=on-demand-pass" rel="noopener noreferrer"&gt;guide&lt;/a&gt; to do this.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By default the network in &lt;code&gt;_app.tsx&lt;/code&gt; is Mainnet, we need to change it to Mumbai&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import type { AppProps } from "next/app";
import { ChainId, ThirdwebProvider } from "@thirdweb-dev/react";

// This is the chainId your dApp will work on.
const activeChainId = ChainId.Mumbai;

function MyApp({ Component, pageProps }: AppProps) {
  return (
    &amp;lt;ThirdwebProvider desiredChainId={activeChainId}&amp;gt;
      &amp;lt;Component {...pageProps} /&amp;gt;
    &amp;lt;/ThirdwebProvider&amp;gt;
  );
}

export default MyApp;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating an NFT collection
&lt;/h2&gt;

&lt;p&gt;We also need to create an NFT collection contract where all the passes will live.&lt;br&gt;
So, go to the &lt;a href="https://thirdweb.com/dashboard" rel="noopener noreferrer"&gt;thirdweb dashboard&lt;/a&gt; and create an NFT collection!&lt;/p&gt;

&lt;p&gt;Fill out the details and deploy the contract!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fohixrurpf4j45pjlia02.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fohixrurpf4j45pjlia02.png" alt="Deploy NFT Collection"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We don't need to do anything else for now, all the NFTs will be minted as the users start minting! So let's get started with the code.&lt;/p&gt;
&lt;h2&gt;
  
  
  Making the website
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Creating an API for generating a signature
&lt;/h3&gt;

&lt;p&gt;We are going to use the signature minting on our backend. You can also add different checks if you want like different price for different wallets, allowing users to mint only 1 pass, etc.&lt;/p&gt;

&lt;p&gt;Create a new folder &lt;code&gt;api&lt;/code&gt; in the pages folder and &lt;code&gt;generate-mint-sig.ts&lt;/code&gt; inside it.&lt;/p&gt;

&lt;p&gt;We will now build a basic API that will output "gm wagmi"&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import type { NextApiRequest, NextApiResponse } from "next";

const generateMintSignature = async (
  req: NextApiRequest,
  res: NextApiResponse
) =&amp;gt; {
  res.send("gm wagmi");
};

export default generateMintSignature;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates a basic API for us, if you now go to the &lt;a href="http://localhost:3000/api/generate-mint-sig" rel="noopener noreferrer"&gt;&lt;code&gt;api/generate-mint-sig&lt;/code&gt;&lt;/a&gt;&lt;br&gt;
endpoint, you will get a response of &lt;code&gt;gm wagmi&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw0eui0ocepm4q2kqh2ax.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw0eui0ocepm4q2kqh2ax.png" alt="Api endpoint"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's now initialize the &lt;a href="https://portal.thirdweb.com/building-web3-apps/setting-up-the-sdk?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=on-demand-pass" rel="noopener noreferrer"&gt;thirdweb SDK&lt;/a&gt;!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const sdk = ThirdwebSDK.fromPrivateKey(
  process.env.PRIVATE_KEY as string,
  "mumbai"
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, we are using an environment variable to initialize the sdk.&lt;br&gt;
The variable is called &lt;code&gt;PRIVATE_KEY&lt;/code&gt;, which is the wallet's private key.&lt;br&gt;
Create a new file &lt;code&gt;.env.local&lt;/code&gt; and add your private key.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PRIVATE_KEY=&amp;lt;private_key&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;How to export your private key&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Learn how to &lt;a href="https://portal.thirdweb.com/guides/create-a-metamask-wallet?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=on-demand-pass#export-your-private-key" rel="noopener noreferrer"&gt;export your private key&lt;/a&gt; from your wallet.&lt;/p&gt;

&lt;p&gt;To do this, create a file called &lt;code&gt;.env.local&lt;/code&gt; at the root of your project, and add the following to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PRIVATE_KEY=your-private-key-here
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Warning&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ensure you store and access your private key securely.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Never&lt;/strong&gt; commit any file that may contain your private key to your source control.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We also need to import the &lt;code&gt;ThirdwebSDK&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;import { ThirdwebSDK } from "@thirdweb-dev/sdk";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Generating the signature&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Finally, we are going to access the NFT Collection using the sdk and generate a signature from it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const { address } = JSON.parse(req.body);

const collection = sdk.getNFTCollection(
  "0xeED8165505d78D2CA9f2b4fA6Aff179CeBd4dCA4"
);

const metadata = {
  name: "Thirdweb",
  description: "Build web3 apps, easily.",
  image: readFileSync(path.join(process.cwd(), "public", "thirdweb.svg")),
  properties: {
    web: "3",
  },
};

try {
  const signedPayload = await collection.signature.generate({
    to: address,
    metadata,
  });

  return res.status(200).json({
    signedPayload,
  });
} catch (error) {
  console.log(error);
  return res.status(500).json({
    error,
  });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is an example of a free mint, you can pass in different properties like price to customize your NFT collection! And as you can see we have created a new metadata object with data of the pass so you need to change the details like name, image, description, and properties based on your needs! For the image we are using a local file which is in the public folder so make sure to put in the correct path.&lt;/p&gt;

&lt;h3&gt;
  
  
  Calling the API from the frontend
&lt;/h3&gt;

&lt;p&gt;In &lt;code&gt;index.tsx&lt;/code&gt; update the address ternary and add the Mint button:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div&amp;gt;
  {address ? (
    &amp;lt;button onClick={mint}&amp;gt;Mint&amp;lt;/button&amp;gt;
  ) : (
    &amp;lt;button onClick={connectWithMetamask}&amp;gt;Connect with Metamask&amp;lt;/button&amp;gt;
  )}
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we will create the mint function that makes an api call to the backend and mints the NFT:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const collection = useNFTCollection(
  "0xeED8165505d78D2CA9f2b4fA6Aff179CeBd4dCA4"
);

const mint = async () =&amp;gt; {
  const signedPayloadReq = await fetch("/api/generate-mint-sig", {
    method: "POST",
    body: JSON.stringify({ address }),
  });

  const signedPayload = await signedPayloadReq.json();

  try {
    const nft = await collection?.signature.mint(signedPayload.signedPayload);
    return nft;
  } catch (err) {
    console.error(err);
    return null;
  }
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we now try minting the NFT, we will be able to mint the NFT successfully!&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>nft</category>
      <category>web3</category>
    </item>
    <item>
      <title>Create a Discord Bot that Assigns a Role to NFT Holders</title>
      <dc:creator>Jarrod Watts</dc:creator>
      <pubDate>Mon, 25 Jul 2022 06:25:21 +0000</pubDate>
      <link>https://forem.com/thirdweb/create-a-discord-bot-that-assigns-a-role-to-nft-holders-50k1</link>
      <guid>https://forem.com/thirdweb/create-a-discord-bot-that-assigns-a-role-to-nft-holders-50k1</guid>
      <description>&lt;p&gt;In this guide, we'll set up a Discord bot that checks if a wallet has an NFT from a collection, and grants them a special role on our Discord server if they do!&lt;/p&gt;

&lt;p&gt;Similar to &lt;a href="https://collab.land/"&gt;Collab.Land&lt;/a&gt;, we'll ask the user to sign in with their wallet as well as their Discord account on our web application, and ask a bot we create to grant them a role on our server using the Discord API running on a Next.js API route.&lt;/p&gt;

&lt;p&gt;You can grab the source code for this project using this link: &lt;a href="https://github.com/thirdweb-example/discord-role-granter"&gt;https://github.com/thirdweb-example/discord-role-granter&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's do it!&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a thirdweb app
&lt;/h2&gt;

&lt;p&gt;To get started, we can use the &lt;a href="https://portal.thirdweb.com/thirdweb-cli?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=discord-role-granter"&gt;thirdweb CLI&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx thirdweb create
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We'll be using TypeScript and Next.js for this guide; so give your app a name and select &lt;strong&gt;Next.js&lt;/strong&gt; for the framework, and &lt;strong&gt;TypeScript&lt;/strong&gt; for the language.&lt;/p&gt;

&lt;p&gt;For this guide, we'll assume you already have a Discord server created and a role set up in the server. If you don't have one, go ahead and create one now and come back to this guide, because next up, we'll create a bot and invite it to our server!&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating A Discord Bot
&lt;/h2&gt;

&lt;p&gt;To create a Discord bot, head to the &lt;a href="https://discord.com/developers/applications"&gt;Discord Developer Portal&lt;/a&gt; and click on &lt;code&gt;New Application&lt;/code&gt;, give it a name and click &lt;code&gt;create&lt;/code&gt;!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hra5WPOD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1658378066493/uTAi0N7I-.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hra5WPOD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1658378066493/uTAi0N7I-.png" alt="image.png" width="466" height="399"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once it's created, head to the &lt;code&gt;Bot&lt;/code&gt; tab, and click &lt;code&gt;Add Bot&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sUiP16ch--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1658378135064/eGNkkLpf3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sUiP16ch--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1658378135064/eGNkkLpf3.png" alt="image.png" width="483" height="240"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Give your bot a username, and I'm unchecking the &lt;code&gt;Public Bot&lt;/code&gt; field so that only we can invite our bot.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--toq4V0Xk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1658378382494/i5srin_Du.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--toq4V0Xk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1658378382494/i5srin_Du.png" alt="image.png" width="880" height="328"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Scroll down to &lt;code&gt;Bot Permissions&lt;/code&gt; and give our bot the &lt;code&gt;Manage Roles&lt;/code&gt; permission:&lt;/p&gt;

&lt;p&gt;It's important to note that you should only give your bot the roles it requires. If your bot token is compromised, other users can perform any actions you have permitted it to do.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iqlNvBD7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1658378279649/0SCOzdku8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iqlNvBD7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1658378279649/0SCOzdku8.png" alt="image.png" width="880" height="211"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you're ready, click &lt;code&gt;Save Changes&lt;/code&gt;!&lt;/p&gt;

&lt;p&gt;Now we're ready to invite our bot to our server!&lt;/p&gt;

&lt;p&gt;Click &lt;code&gt;OAuth2&lt;/code&gt; &amp;gt; &lt;code&gt;URL Generator&lt;/code&gt; on the sidebar:&lt;/p&gt;

&lt;p&gt;Select &lt;code&gt;bot&lt;/code&gt; and &lt;code&gt;Manage Roles&lt;/code&gt; scopes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OQYrLjVc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1658378764505/Q6hmuH8Ml.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OQYrLjVc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1658378764505/Q6hmuH8Ml.png" alt="image.png" width="880" height="633"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Copy the Generated URL and open it in your browser.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4HbyBGee--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1658378817253/bzEMllDkE.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4HbyBGee--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1658378817253/bzEMllDkE.png" alt="image.png" width="880" height="530"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Make sure it is the bot you expect, select the server you want to add your bot to and click &lt;code&gt;Continue&lt;/code&gt;. It will ask you to approve this bot's permissions, you should see a prompt to authorize the bot for &lt;code&gt;Manage Roles&lt;/code&gt; permissions:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4vdsLwO7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1658378873543/clVZw5YdI.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4vdsLwO7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1658378873543/clVZw5YdI.png" alt="image.png" width="398" height="526"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click &lt;code&gt;Authorise&lt;/code&gt;, once successful, you'll see an &lt;code&gt;Authorised&lt;/code&gt; window&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--23-7CKSo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1658378937976/yuvDcAWEG.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--23-7CKSo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1658378937976/yuvDcAWEG.png" alt="image.png" width="558" height="528"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And your bot will be added to your server - say hi!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BtA8GEeT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1658378948085/jchIC5F1o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BtA8GEeT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1658378948085/jchIC5F1o.png" alt="image.png" width="497" height="56"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Authenticating Users
&lt;/h2&gt;

&lt;p&gt;To authenticate users with Discord, we'll be using the library `&lt;a href="https://next-auth.js.org/"&gt;NextAuth&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Create a new folder inside of &lt;code&gt;pages&lt;/code&gt; called &lt;code&gt;api&lt;/code&gt;, and within that, create another folder called &lt;code&gt;auth&lt;/code&gt;, and within this &lt;code&gt;auth&lt;/code&gt; folder, create a file called &lt;code&gt;[...nextauth].ts&lt;/code&gt;!&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;bash&lt;br&gt;
yarn add next-auth&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This is where we'll configure our NextAuth setup and allow people to sign in to our application using Discord.&lt;/p&gt;

&lt;p&gt;Back in your Discord Developer Portal, copy across your &lt;code&gt;Client ID&lt;/code&gt; and &lt;code&gt;Client Secret&lt;/code&gt; into environment variables in your project, by creating a &lt;code&gt;.env.local&lt;/code&gt; file at the root of the directory.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qc53dKyM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1658380648801/1rp4zc2-a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qc53dKyM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1658380648801/1rp4zc2-a.png" alt="image.png" width="880" height="273"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;text&lt;br&gt;
CLIENT_ID=xxxxx&lt;br&gt;
CLIENT_SECRET=xxxxx&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We also need to add a Redirect URL into our Application while we're here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tExQAOlo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1658443956419/84fGElQk0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tExQAOlo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1658443956419/84fGElQk0.png" alt="image.png" width="880" height="329"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now let's make our &lt;code&gt;[...nextauth]&lt;/code&gt; API route look like this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`ts&lt;br&gt;
import NextAuth from "next-auth";&lt;br&gt;
import DiscordProvider from "next-auth/providers/discord";&lt;br&gt;
export default NextAuth({&lt;br&gt;
  // Configure one or more authentication providers&lt;br&gt;
  providers: [&lt;br&gt;
    DiscordProvider({&lt;br&gt;
      clientId: process.env.CLIENT_ID as string,&lt;br&gt;
      clientSecret: process.env.CLIENT_SECRET as string,&lt;br&gt;
    }),&lt;br&gt;
  ],&lt;/p&gt;

&lt;p&gt;// When the user signs in, get their token&lt;br&gt;
  callbacks: {&lt;br&gt;
    async jwt({ token, account }) {&lt;br&gt;
      // Persist the OAuth access_token to the token right after signin&lt;br&gt;
      if (account) {&lt;br&gt;
        token.userId = account.providerAccountId;&lt;br&gt;
      }&lt;br&gt;
      return token;&lt;br&gt;
    },&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;async session({ session, token, user }) {
  // Send properties to the client, like an access_token from a provider.
  session.userId = token.userId;
  return session;
},
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;},&lt;br&gt;
});&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You might notice we have some modifications to the data that gets returned inside these callbacks. We're doing this to add the user's ID into the token that gets returned by NextAuth, because we want to access that value when we try and grant this user the role (we'll need their ID).&lt;/p&gt;

&lt;p&gt;To access NextAuth's hooks such as &lt;code&gt;signIn&lt;/code&gt;, we need to wrap our application in the &lt;code&gt;SessionProvider&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`jsx&lt;br&gt;
import type { AppProps } from "next/app";&lt;br&gt;
import { ChainId, ThirdwebProvider } from "@thirdweb-dev/react";&lt;br&gt;
import { SessionProvider } from "next-auth/react";&lt;br&gt;
import "../styles/globals.css";&lt;/p&gt;

&lt;p&gt;// This is the chainId your dApp will work on.&lt;br&gt;
const activeChainId = ChainId.Mumbai;&lt;/p&gt;

&lt;p&gt;function MyApp({ Component, pageProps }: AppProps) {&lt;br&gt;
  return (&lt;br&gt;
    &lt;br&gt;
      &lt;br&gt;
        &lt;br&gt;
      &lt;br&gt;
    &lt;br&gt;
  );&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;export default MyApp;&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now we're ready for users to authenticate to our application using Discord!&lt;/p&gt;

&lt;p&gt;Let's create a folder called &lt;code&gt;components&lt;/code&gt; and create a &lt;code&gt;SignIn.tsx&lt;/code&gt; component within that folder. This component will ask the user to both:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Sign In With Their Wallet&lt;/li&gt;
&lt;li&gt;Authenticate With Discord&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In this component, three states can occur:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The user is connected to both &lt;code&gt;wallet&lt;/code&gt; and &lt;code&gt;Discord&lt;/code&gt; =&amp;gt; We show them the main page.&lt;/li&gt;
&lt;li&gt;The user is not connected to &lt;code&gt;wallet&lt;/code&gt; =&amp;gt; We ask them to connect their wallet.&lt;/li&gt;
&lt;li&gt;The user is not connected to &lt;code&gt;Discord&lt;/code&gt;=&amp;gt; We ask them to authenticate with Discord.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once the user is in state &lt;code&gt;1&lt;/code&gt;, (has both wallet connected and Discord connected), we can show them a button that will run some code on our server to check if they own an NFT. If they do own the NFT, our Discord bot will assign them a role in our Discord server!&lt;/p&gt;

&lt;p&gt;Let's write the code for these three states:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Imports and hook definitions&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`jsx&lt;br&gt;
import { useAddress, useDisconnect, useMetamask } from "@thirdweb-dev/react";&lt;br&gt;
import { useSession, signIn, signOut } from "next-auth/react";&lt;br&gt;
import React from "react";&lt;br&gt;
import styles from "../styles/Home.module.css";&lt;/p&gt;

&lt;p&gt;export default function SignIn() {&lt;br&gt;
  const address = useAddress();&lt;br&gt;
  const connectWithMetamask = useMetamask();&lt;br&gt;
  const disconnectWallet = useDisconnect();&lt;br&gt;
  const { data: session } = useSession();&lt;/p&gt;

&lt;p&gt;// rest of the code here&lt;br&gt;
}&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;State 1 - Both Wallet + Discord Connected&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;jsx&lt;br&gt;
// 1. The user is signed into discord and connected to wallet.&lt;br&gt;
if (session &amp;amp;&amp;amp; address) {&lt;br&gt;
  return (&lt;br&gt;
    &amp;lt;div className={styles.bigSpacerTop}&amp;gt;&lt;br&gt;
      &amp;lt;a onClick={() =&amp;gt; signOut()} className={styles.secondaryButton}&amp;gt;&lt;br&gt;
        Sign out of Discord&lt;br&gt;
      &amp;lt;/a&amp;gt;&lt;br&gt;
      |&amp;lt;a onClick={() =&amp;gt; disconnectWallet()} className={styles.secondaryButton}&amp;gt;&lt;br&gt;
        Disconnect wallet&lt;br&gt;
      &amp;lt;/a&amp;gt;&lt;br&gt;
    &amp;lt;/div&amp;gt;&lt;br&gt;
  );&lt;br&gt;
}&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;State 2 - Connect Wallet&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;jsx&lt;br&gt;
// 2. Connect Wallet&lt;br&gt;
if (!address) {&lt;br&gt;
  return (&lt;br&gt;
    &amp;lt;div className={styles.main}&amp;gt;&lt;br&gt;
      &amp;lt;h2 className={styles.noGapBottom}&amp;gt;Connect Your Wallet&amp;lt;/h2&amp;gt;&lt;br&gt;
      &amp;lt;p&amp;gt;Connect your wallet to check eligibility.&amp;lt;/p&amp;gt;&lt;br&gt;
      &amp;lt;button&lt;br&gt;
        onClick={connectWithMetamask}&lt;br&gt;
        className={&lt;/code&gt;${styles.mainButton} ${styles.spacerTop}&lt;code&gt;}&lt;br&gt;
      &amp;gt;&lt;br&gt;
        Connect Wallet&lt;br&gt;
      &amp;lt;/button&amp;gt;&lt;br&gt;
    &amp;lt;/div&amp;gt;&lt;br&gt;
  );&lt;br&gt;
}&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;State 3 - Connect Discord&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;jsx&lt;br&gt;
// 3. Connect with Discord (OAuth)&lt;br&gt;
if (!session) {&lt;br&gt;
  return (&lt;br&gt;
    &amp;lt;div className={&lt;/code&gt;${styles.main}`}&amp;gt;&lt;br&gt;
      &lt;/p&gt;
&lt;h2&gt;Sign In with Discord&lt;/h2&gt;
&lt;br&gt;
      &lt;p&gt;Sign In with Discord to check your eligibility for the NFT!&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  &amp;lt;button
    onClick={() =&amp;gt; signIn("discord")}
    className={`${styles.mainButton} ${styles.spacerTop}`}
  &amp;gt;
    Connect Discord
  &amp;lt;/button&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;);&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;// default return nothing&lt;br&gt;
return null;&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Back on our home page, let's change the logic to show the user the &lt;code&gt;SignIn&lt;/code&gt; component when we can't find both an &lt;code&gt;address&lt;/code&gt; and &lt;code&gt;session&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`jsx&lt;br&gt;
// index.tsx&lt;br&gt;
import { useAddress, useSDK } from "@thirdweb-dev/react";&lt;br&gt;
import { useSession } from "next-auth/react";&lt;br&gt;
import SignIn from "../components/SignIn";&lt;br&gt;
import type { NextPage } from "next";&lt;br&gt;
import styles from "../styles/Home.module.css";&lt;/p&gt;

&lt;p&gt;const Home: NextPage = () =&amp;gt; {&lt;br&gt;
  const address = useAddress();&lt;br&gt;
  const { data: session } = useSession();&lt;br&gt;
  const sdk = useSDK();&lt;/p&gt;

&lt;p&gt;return (&lt;br&gt;
    &lt;/p&gt;
&lt;br&gt;
      &lt;br&gt;
        
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    {address &amp;amp;&amp;amp; session &amp;amp;&amp;amp; (
      &amp;lt;div className={styles.collectionContainer}&amp;gt;
        &amp;lt;button className={styles.mainButton}&amp;gt;Give me the role!&amp;lt;/button&amp;gt;
      &amp;lt;/div&amp;gt;
    )}
  &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;);&lt;br&gt;
};&lt;/p&gt;

&lt;p&gt;export default Home;&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We now have a page that prompts the user to connect their wallet, and then Sign In With Discord:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7H8dstIH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1658444991246/-4ul2aaax.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7H8dstIH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1658444991246/-4ul2aaax.png" alt="image.png" width="714" height="492"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you click the &lt;code&gt;Connect Discord&lt;/code&gt; button, NextAuth handles the OAuth flow for us:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0VPTp3Ah--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1658445042195/hunL0jqm8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0VPTp3Ah--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1658445042195/hunL0jqm8.png" alt="image.png" width="637" height="361"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the user has connected both their wallet and Discord, we show them a button that says &lt;code&gt;Give me the role!&lt;/code&gt;, we'll add some functionality to this button next!&lt;/p&gt;

&lt;h2&gt;
  
  
  Granting Discord Roles
&lt;/h2&gt;

&lt;p&gt;To grant a role to the connected user, we are going to use the Discord API on behalf of the bot that we created. Specifically, we'll be hitting the &lt;code&gt;Add Guild Member Role&lt;/code&gt; API endpoint:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--o0PQYfHH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1658455468735/Pe6SJyvls.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--o0PQYfHH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1658455468735/Pe6SJyvls.png" alt="image.png" width="852" height="261"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To make requests from our bot, we'll need a token to act on its behalf. To generate a token, head to the &lt;code&gt;Bot&lt;/code&gt; tab from your Discord Developer portal, and click &lt;code&gt;Reset Token&lt;/code&gt; on your bot:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gLm60Ymz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1658455558002/Y1ZUud12k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gLm60Ymz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1658455558002/Y1ZUud12k.png" alt="image.png" width="880" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We then need to store this inside our environment variables as well securely:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;text&lt;br&gt;
BOT_TOKEN=xxxx&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Next, let's make another API route in our &lt;code&gt;api&lt;/code&gt; folder called &lt;code&gt;grant-role.ts&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Within this API route, we're going to grant a user the discord role &lt;em&gt;if&lt;/em&gt; they own an NFT from our collection. This involves a few steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Authenticate the login payload of the user (ensure the user owns the wallet)&lt;/li&gt;
&lt;li&gt;Check that wallet's NFT balance&lt;/li&gt;
&lt;li&gt;Make a request to the Discord API to grant a role&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Firstly, let's set up the barebones of our API route:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`ts&lt;br&gt;
import { ThirdwebSDK } from "@thirdweb-dev/sdk";&lt;br&gt;
import type { NextApiRequest, NextApiResponse } from "next";&lt;br&gt;
import { getSession } from "next-auth/react";&lt;/p&gt;

&lt;p&gt;export default async function grantRole(&lt;br&gt;
  req: NextApiRequest,&lt;br&gt;
  res: NextApiResponse,&lt;br&gt;
) {&lt;br&gt;
  // Get the login payload out of the request&lt;br&gt;
  const { loginPayload } = JSON.parse(req.body);&lt;/p&gt;

&lt;p&gt;// Get the NextAuth session so we can use the user ID as part of the discord API request&lt;br&gt;
  const session = await getSession({ req });&lt;/p&gt;

&lt;p&gt;if (!session) {&lt;br&gt;
    res.status(401).json({ error: "Not logged in" });&lt;br&gt;
    return;&lt;br&gt;
  }&lt;br&gt;
}&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Authenticate the login payload
&lt;/h3&gt;

&lt;p&gt;On the client, we're going to ask the user to sign in using the &lt;a href="https://thirdweb.com/authentication?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=discord-role-granter"&gt;Authentication SDK&lt;/a&gt;. This requires the user to sign a message which generates a login payload; we'll be sending this in the body of the request.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`jsx&lt;br&gt;
// Authenticate login payload&lt;br&gt;
const sdk = new ThirdwebSDK("mumbai");&lt;br&gt;
const domain = "thirdweb.com"; // This should be the domain name of your own website&lt;br&gt;
// Verify the login payload is real and valid&lt;br&gt;
const verifiedWalletAddress = sdk.auth.verify(domain, loginPayload);&lt;/p&gt;

&lt;p&gt;// If the login payload is not valid, return an error&lt;br&gt;
if (!verifiedWalletAddress) {&lt;br&gt;
  res.status(401).json({ error: "Invalid login payload" });&lt;br&gt;
  return;&lt;br&gt;
}&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This step ensures that the user owns the wallet that we are going to check. It prevents users from sending a wallet address that is not theirs to this API endpoint, and falsely granting them the role.&lt;/p&gt;

&lt;h3&gt;
  
  
  Check the wallet's NFT balance
&lt;/h3&gt;

&lt;p&gt;We use the SDK to view the balance of the wallet address for token ID &lt;code&gt;0&lt;/code&gt; of our ERC-1155 NFT collection.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`ts&lt;br&gt;
// Check if this user owns an NFT&lt;br&gt;
const editionDrop = sdk.getEditionDrop(&lt;br&gt;
  "0x1fCbA150F05Bbe1C9D21d3ab08E35D682a4c41bF",&lt;br&gt;
);&lt;/p&gt;

&lt;p&gt;// Get addresses' balance of token ID 0&lt;br&gt;
const balance = await editionDrop.balanceOf(verifiedWalletAddress, 0);&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Granting Users the role
&lt;/h3&gt;

&lt;p&gt;Here, we make the request to the discord API to grant the user a role by using our bot token as the authorization header.&lt;/p&gt;

&lt;p&gt;In order to do this, you'll need to create a role in your server, and copy both your &lt;code&gt;server&lt;/code&gt; and &lt;code&gt;role&lt;/code&gt; ID into the variables. You can learn how to do that from &lt;a href="https://support.discord.com/hc/en-us/articles/206346498-Where-can-I-find-my-User-Server-Message-ID-"&gt;this guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`ts&lt;br&gt;
if (balance.toNumber() &amp;gt; 0) {&lt;br&gt;
  // If the user is verified and has an NFT, return the content&lt;/p&gt;

&lt;p&gt;// Make a request to the Discord API to get the servers this user is a part of&lt;br&gt;
  const discordServerId = "999533680663998485";&lt;br&gt;
  const { userId } = session;&lt;br&gt;
  const roleId = "999851736028172298";&lt;br&gt;
  const response = await fetch(&lt;br&gt;
    // Discord Developer Docs for this API Request: &lt;a href="https://discord.com/developers/docs/resources/guild#add-guild-member-role"&gt;https://discord.com/developers/docs/resources/guild#add-guild-member-role&lt;/a&gt;&lt;br&gt;
    &lt;code&gt;https://discordapp.com/api/guilds/${discordServerId}/members/${userId}/roles/${roleId}&lt;/code&gt;,&lt;br&gt;
    {&lt;br&gt;
      headers: {&lt;br&gt;
        // Use the bot token to grant the role&lt;br&gt;
        Authorization: &lt;code&gt;Bot ${process.env.BOT_TOKEN}&lt;/code&gt;,&lt;br&gt;
      },&lt;br&gt;
      method: "PUT",&lt;br&gt;
    },&lt;br&gt;
  );&lt;/p&gt;

&lt;p&gt;// If the role was granted, return the content&lt;br&gt;
  if (response.ok) {&lt;br&gt;
    res.status(200).json({ message: "Role granted" });&lt;br&gt;
  }&lt;/p&gt;

&lt;p&gt;// Something went wrong granting the role, but they do have an NFT&lt;br&gt;
  else {&lt;br&gt;
    res&lt;br&gt;
      .status(500)&lt;br&gt;
      .json({ error: "Error granting role, are you in the server?" });&lt;br&gt;
  }&lt;br&gt;
}&lt;br&gt;
// If the user is verified but doesn't have an NFT, return an error&lt;br&gt;
else {&lt;br&gt;
  res.status(401).json({ error: "User does not have an NFT" });&lt;br&gt;
}&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;That's it for our API route, now we need to call this from our client!&lt;/p&gt;

&lt;p&gt;Back on the &lt;code&gt;index.tsx&lt;/code&gt; page, let's create a function called &lt;code&gt;requestGrantRole&lt;/code&gt; &lt;em&gt;inside&lt;/em&gt; the component and make a fetch request to this API endpoint.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`tsx&lt;br&gt;
const sdk = useSDK();&lt;/p&gt;

&lt;p&gt;async function requestGrantRole() {&lt;br&gt;
  // First, login and sign a message&lt;br&gt;
  const domain = "thirdweb.com"; // This should be the domain name of your own website&lt;br&gt;
  const loginPayload = await sdk?.auth.login(domain);&lt;/p&gt;

&lt;p&gt;// Then make a request to our API endpoint.&lt;br&gt;
  try {&lt;br&gt;
    const response = await fetch("/api/grant-role", {&lt;br&gt;
      method: "POST",&lt;br&gt;
      body: JSON.stringify({&lt;br&gt;
        loginPayload,&lt;br&gt;
      }),&lt;br&gt;
    });&lt;br&gt;
    const data = await response.json();&lt;br&gt;
    console.log(data);&lt;br&gt;
  } catch (e) {&lt;br&gt;
    console.error(e);&lt;br&gt;
  }&lt;br&gt;
}&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;And attach this function to our button:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;tsx&lt;br&gt;
&amp;lt;button className={styles.mainButton} onClick={requestGrantRole}&amp;gt;&lt;br&gt;
  Give me the role!&lt;br&gt;
&amp;lt;/button&amp;gt;&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;That's it! We're ready to test it out!&lt;/p&gt;

&lt;h3&gt;
  
  
  Demo
&lt;/h3&gt;

&lt;p&gt;Connect our wallet, authenticate with Discord, and sign in with Ethereum:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--C55R8psK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1658461183495/yD-KJYnN6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--C55R8psK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1658461183495/yD-KJYnN6.png" alt="image.png" width="880" height="557"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;grant-role&lt;/code&gt; API endpoint runs, granting the connected Discord user the role if they have an NFT from the collection:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HGauSRde--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1658461223440/Un7WxowZ4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HGauSRde--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1658461223440/Un7WxowZ4.png" alt="image.png" width="738" height="110"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We now have the role in our server!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--M11EVLqE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1658461232901/LcwdvJccS.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--M11EVLqE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1658461232901/LcwdvJccS.png" alt="image.png" width="367" height="137"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Going to production
&lt;/h2&gt;

&lt;p&gt;In a production environment, you need to have an environment variable called &lt;code&gt;NEXTAUTH_SECRET&lt;/code&gt; for the Discord Oauth to work.&lt;/p&gt;

&lt;p&gt;You can learn more about it here:&lt;br&gt;
&lt;a href="https://next-auth.js.org/configuration/options"&gt;https://next-auth.js.org/configuration/options&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can quickly create a good value on the command line via this &lt;code&gt;openssl&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;bash&lt;br&gt;
openssl rand -base64 32&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;And add it as an environment variable in your &lt;code&gt;.env.local&lt;/code&gt; file:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;&lt;br&gt;
NEXTAUTH_SECRET=&amp;lt;your-value-here&amp;gt;&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;We've made our very own Discord role granting application using thirdweb, the Discord API, and NextAuth!&lt;/p&gt;

&lt;p&gt;You can check out the full code for this project on our GitHub:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/thirdweb-example/discord-role-granter"&gt;https://github.com/thirdweb-example/discord-role-granter&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For any questions, suggestions, join our discord at &lt;a href="https://discord.gg/thirdweb"&gt;https://discord.gg/cd thirdweb&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>web3</category>
      <category>blockchain</category>
      <category>discord</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Create Simultaneous Allowlists with Signature Drop and Next.js</title>
      <dc:creator>Avneesh Agarwal</dc:creator>
      <pubDate>Wed, 20 Jul 2022 16:47:43 +0000</pubDate>
      <link>https://forem.com/thirdweb/create-simultaneous-allowlists-with-signature-drop-and-nextjs-3aco</link>
      <guid>https://forem.com/thirdweb/create-simultaneous-allowlists-with-signature-drop-and-nextjs-3aco</guid>
      <description>&lt;p&gt;Learn how to create simultaneous allowlists where different users can buy NFTs from the drop at a different price based on which allowlist they are in&lt;/p&gt;

&lt;h2&gt;
  
  
  What is thirdweb?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://thirdweb.com/dashboard?utm_source=hashnode&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=simultaneous-allowlists" rel="noopener noreferrer"&gt;thirdweb&lt;/a&gt; is a platform that lets you deploy smart contracts without having to know Solidity, you can do it by using TypeScript, Python or Go or even without writing any code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In this guide, we are going to create a &lt;a href="https://portal.thirdweb.com/pre-built-contracts/signature-drop?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=simultaneous-allowlists" rel="noopener noreferrer"&gt;Signature drop&lt;/a&gt; where users&lt;br&gt;
will be able to connect their wallets to the website and claim an NFT from the drop. Once the user clicks &lt;code&gt;Mint&lt;/code&gt;, we will make an&lt;br&gt;
API request that checks if the user is in one of our allowlists.&lt;/p&gt;

&lt;p&gt;Based on the check, we will generate a signature with a different price for each allowlist! Let's get started.&lt;/p&gt;
&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;p&gt;I am going to use the &lt;a href="https://github.com/thirdweb-example/next-typescript-starter" rel="noopener noreferrer"&gt;Next typescript starter template&lt;/a&gt; for this guide.&lt;/p&gt;

&lt;p&gt;If you are following along with the guide, you can create a project with the&lt;br&gt;
&lt;a href="https://github.com/thirdweb-example/next-typescript-starter" rel="noopener noreferrer"&gt;Next TypeScript template&lt;/a&gt; using the &lt;a href="https://portal.thirdweb.com/thirdweb-cli?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=simultaneous-allowlists" rel="noopener noreferrer"&gt;thirdweb CLI&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx thirdweb create &lt;span class="nt"&gt;--next&lt;/span&gt; &lt;span class="nt"&gt;--ts&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you already have a Next.js app you can simply follow these steps to get started:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install &lt;code&gt;@thirdweb-dev/react&lt;/code&gt; and &lt;code&gt;@thirdweb-dev/sdk&lt;/code&gt; and &lt;code&gt;ethers&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Add MetaMask authentication to the site. You can follow this &lt;a href="https://dev.to/guides/add-connectwallet-to-your-website"&gt;guide&lt;/a&gt; to do this.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By default the network in &lt;code&gt;_app.tsx&lt;/code&gt; is Mainnet, we need to change it to Mumbai&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import type { AppProps } from "next/app";
import { ChainId, ThirdwebProvider } from "@thirdweb-dev/react";

// This is the chainId your dApp will work on.
const activeChainId = ChainId.Mumbai;

function MyApp({ Component, pageProps }: AppProps) {
  return (
    &amp;lt;ThirdwebProvider desiredChainId={activeChainId}&amp;gt;
      &amp;lt;Component {...pageProps} /&amp;gt;
    &amp;lt;/ThirdwebProvider&amp;gt;
  );
}

export default MyApp;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating a Signature Drop and batch Uploading NFTs
&lt;/h2&gt;

&lt;p&gt;We also need to create a Signature Drop and upload a bunch of NFTs that users can claim.&lt;br&gt;
So, go to the &lt;a href="https://thirdweb.com/dashboard?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=simultaneous-allowlists" rel="noopener noreferrer"&gt;thirdweb dashboard&lt;/a&gt; and create a signature drop!&lt;/p&gt;

&lt;p&gt;Fill out the details and deploy the contract!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1658190708575%2FjYoXLOtEm.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1658190708575%2FjYoXLOtEm.png" alt="Deploy Signature Drop"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, let's batch upload some NFTs for the users to mint!&lt;br&gt;
I am going to use the &lt;a href="https://github.com/nachoiacovino/thirdweb-pokemon" rel="noopener noreferrer"&gt;Pokemon batch upload example&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Click on batch upload and upload the images and the CSV/JSON file.&lt;/p&gt;

&lt;p&gt;Once they are uploaded you will be able to see the NFTs! To learn more about batch upload check out &lt;a href="https://portal.thirdweb.com/guides/how-to-batch-upload?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=simultaneous-allowlists" rel="noopener noreferrer"&gt;this guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1658190735032%2FnIvfmV8Jh.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1658190735032%2FnIvfmV8Jh.png" alt="Batch uploaded NFTs"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Making the website
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Creating an API for generating a signature
&lt;/h3&gt;

&lt;p&gt;We are going to use the signature minting on our backend to check the price at which this user will mint the NFT!&lt;/p&gt;

&lt;p&gt;Create a new folder &lt;code&gt;api&lt;/code&gt; in the pages folder and &lt;code&gt;generate-mint-sig.ts&lt;/code&gt; inside it.&lt;/p&gt;

&lt;p&gt;We will now build a basic API that will output "gm wagmi"&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import type { NextApiRequest, NextApiResponse } from "next";

const generateMintSignature = async (
  req: NextApiRequest,
  res: NextApiResponse,
) =&amp;gt; {
  res.send("gm wagmi");
};

export default generateMintSignature;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates a basic API for us, if you now go to the &lt;a href="http://localhost:3000/api/generate-mint-sig" rel="noopener noreferrer"&gt;&lt;code&gt;api/generate-mint-sig&lt;/code&gt;&lt;/a&gt;&lt;br&gt;
endpoint, you will get a response of &lt;code&gt;Gm wagmi&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1658190910036%2FiYpyVBO1b.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1658190910036%2FiYpyVBO1b.png" alt="Api response"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's now initialize the &lt;a href="https://portal.thirdweb.com/building-web3-apps/setting-up-the-sdk?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=simultaneous-allowlists" rel="noopener noreferrer"&gt;thirdweb SDK&lt;/a&gt;!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sdk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ThirdwebSDK&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromPrivateKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PRIVATE_KEY&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mumbai&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, we are using an environment variable to initialize the sdk.&lt;br&gt;
The variable is called &lt;code&gt;PRIVATE_KEY&lt;/code&gt; which is the private key of the wallet.&lt;br&gt;
Create a new file &lt;code&gt;.env.local&lt;/code&gt; and add your private key.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PRIVATE_KEY=&amp;lt;private_key&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;How to export your private key&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Learn how to &lt;a href="https://dev.to/guides/create-a-metamask-wallet#export-your-private-key"&gt;export your private key&lt;/a&gt; from your wallet.&lt;/p&gt;

&lt;p&gt;To do this, create a file called &lt;code&gt;.env.local&lt;/code&gt; at the root of your project, and add the following to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PRIVATE_KEY=your-private-key-here
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ensure you store and access your private key securely.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Never&lt;/strong&gt; commit any file that may contain your private key to your source control.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We also need to import the &lt;code&gt;ThirdwebSDK&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ThirdwebSDK&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@thirdweb-dev/sdk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Determining the price of the NFT&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I am creating 2 hardcoded arrays in this example, but you can get them from a JSON file, from a database, or anything you like!&lt;/p&gt;

&lt;p&gt;So add these 2 arrays and a function to determine the price:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const teamMembers = ["0x39Ab29fAfb5ad19e96CFB1E1c492083492DB89d4"];

const allowList = ["0x6bF08768995E7430184a48e96940B83C15c1653f"];

const determinePrice = (address: string) =&amp;gt; {
  if (teamMembers.includes(address)) {
    return 0;
  }
  if (allowList.includes(address)) {
    return 1;
  }
  return 2;
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So if the person is in the allowlist they will mint the NFT for 1 MATIC, if they are a team member they will mint the NFT for 0 MATIC,&lt;br&gt;
and if they are not in an allowlist, they will mint the NFT for 2 MATIC.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Generating the signature&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Finally, we are going to access the Signature Drop using the sdk and generate a signature from it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const { address } = req.body;

const drop = sdk.getSignatureDrop("0xcB31341eE7FaC6917e8e9D71441747e5FAdA466F");
try {
  const signedPayload = await drop.signature.generate({
    to: address,
    price: determinePrice(address),
  });

  return res.status(200).json({
    signedPayload: signedPayload,
  });
} catch (error) {
  console.log(error);
  return res.status(500).json({
    error,
  });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Calling the API from the frontend
&lt;/h3&gt;

&lt;p&gt;In &lt;code&gt;index.tsx&lt;/code&gt; update the address ternary and add the Mint button:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div&amp;gt;
  {address ? (
    &amp;lt;button onClick={mint}&amp;gt;Mint&amp;lt;/button&amp;gt;
  ) : (
    &amp;lt;button onClick={connectWithMetamask}&amp;gt;Connect with Metamask&amp;lt;/button&amp;gt;
  )}
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we will create the mint function that makes an api call to the backend and mints the NFT:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const drop = useSignatureDrop("0xcB31341eE7FaC6917e8e9D71441747e5FAdA466F");

const mint = async () =&amp;gt; {
  const signedPayloadReq = await fetch("/api/generate-mint-sig", {
    method: "POST",
    body: JSON.stringify({ address }),
  });

  const signedPayload = await signedPayloadReq.json();

  try {
    const nft = await drop?.signature.mint(signedPayload.signedPayload);
    return nft;
  } catch (err) {
    console.error(err);
    return null;
  }
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we now try minting the NFT, we will be able to mint the NFT successfully at different prices! 🎉&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This was a lot, now pat yourself on the back and share your amazing apps with us!&lt;br&gt;
If you want to have a look at the code, check out the &lt;a href="https://github.com/thirdweb-dev/examples/tree/main/typescript/simultaneous-allowlists" rel="noopener noreferrer"&gt;GitHub Repository&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>thirdweb</category>
      <category>web3</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>Create an ERC-721A NFT Collection using thirdweb</title>
      <dc:creator>Jarrod Watts</dc:creator>
      <pubDate>Wed, 20 Jul 2022 04:15:00 +0000</pubDate>
      <link>https://forem.com/thirdweb/create-an-erc-721a-nft-collection-using-thirdweb-4ok0</link>
      <guid>https://forem.com/thirdweb/create-an-erc-721a-nft-collection-using-thirdweb-4ok0</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In this guide, we'll use the &lt;a href="https://portal.thirdweb.com/pre-built-contracts/signature-drop?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=signature-drop"&gt;Signature Drop&lt;/a&gt;&lt;br&gt;
contract to create a collection of NFTs that follow the &lt;a href="https://www.erc721a.org/"&gt;ERC-721A&lt;/a&gt; standard!&lt;/p&gt;

&lt;p&gt;Compared to the regular &lt;a href="https://eips.ethereum.org/EIPS/eip-721"&gt;ERC-721&lt;/a&gt; standard, the ERC-721A implementation&lt;br&gt;
optimizes the gas fees of the contract to enable cheaper gas fees for users when they are minting multiple tokens in one transaction.&lt;/p&gt;

&lt;p&gt;The signature drop contract also enables &lt;a href="https://portal.thirdweb.com/advanced-features/on-demand-minting?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=signature-drop"&gt;Signature-based Minting&lt;/a&gt;&lt;br&gt;
which allows us, (the admin wallet), to approve users' mint requests on-demand if they meet specific criteria, such as being a holder of another token!&lt;/p&gt;
&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;Here's what we'll be doing in this guide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deploying the ERC-721A Signature Drop contract.&lt;/li&gt;
&lt;li&gt;Lazy Minting our NFTs by batch uploading metadata files.&lt;/li&gt;
&lt;li&gt;Creating a web application where users can claim NFTs.&lt;/li&gt;
&lt;li&gt;Adding a special "Discount Claim" button where users who hold an NFT from another collection can claim an NFT for a discount!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Check out the demo here: &lt;a href="https://signature-drop.thirdweb-example.com/"&gt;https://signature-drop.thirdweb-example.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can view the full source code below:&lt;/p&gt;

&lt;p&gt;%[&lt;a href="https://github.com/thirdweb-example/signature-drop"&gt;https://github.com/thirdweb-example/signature-drop&lt;/a&gt;]&lt;/p&gt;
&lt;h2&gt;
  
  
  Creating the Signature Drop Contract
&lt;/h2&gt;

&lt;p&gt;To deploy one of thirdweb's &lt;a href="https://portal.thirdweb.com/smart-contracts/pre-built-contracts-overview?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=signature-drop"&gt;Pre-built contracts&lt;/a&gt;, head to the &lt;a href="https://thirdweb.com/dashboard?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=signature-drop"&gt;dashboard&lt;/a&gt; and connect your wallet.&lt;/p&gt;

&lt;p&gt;If you don't already have a wallet, learn how to get set up with MetaMask in our "&lt;a href="https://portal.thirdweb.com/guides/create-a-metamask-wallet?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=signature-drop"&gt;Guide: Create a MetaMask Wallet&lt;/a&gt;"&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bO-okhzh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1657760009059/qfskZYlOE.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bO-okhzh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1657760009059/qfskZYlOE.png" alt="image.png" width="782" height="483"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From here, click the &lt;code&gt;Deploy New Contract&lt;/code&gt; button -&amp;gt; &lt;code&gt;Pre-Built Contracts&lt;/code&gt; -&amp;gt; &lt;code&gt;Release a drop&lt;/code&gt; -&amp;gt; &lt;code&gt;Signature Drop&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4eA8j3kc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1657760084261/ANCsZaEaV.png%2520align%3D%2522center%2522" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4eA8j3kc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1657760084261/ANCsZaEaV.png%2520align%3D%2522center%2522" alt="image.png" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is where you can upload the metadata for the contract itself. This is the metadata that will show up on pages such as the OpenSea Collection page.&lt;/p&gt;

&lt;p&gt;Give your contract a &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;symbol&lt;/code&gt;, &lt;code&gt;description&lt;/code&gt;, &lt;code&gt;image&lt;/code&gt;, and configure royalty fees as you like! Here's how mine looks:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--crXeqWzI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1657760279907/Mj-8EOO8M.png%2520align%3D%2522center%2522" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--crXeqWzI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1657760279907/Mj-8EOO8M.png%2520align%3D%2522center%2522" alt="image.png" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'll be deploying to the &lt;a href="https://portal.thirdweb.com/guides/which-network-should-you-use#arbitrum?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=signature-drop"&gt;Arbitrum Testnet&lt;/a&gt; as it&lt;br&gt;
offers super-fast transaction approval times (which are great for testing purposes)!&lt;/p&gt;

&lt;p&gt;When you're ready, click &lt;code&gt;Deploy Now&lt;/code&gt;, and approve the &lt;code&gt;Deploy Proxy&lt;/code&gt; transaction in your wallet.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BVm-2b22--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1657760472247/2eSd8OwnC.png%2520align%3D%2522center%2522" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BVm-2b22--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1657760472247/2eSd8OwnC.png%2520align%3D%2522center%2522" alt="image.png" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You just deployed your very own ERC-721A NFT Collection!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WIh9OW39--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1657760613270/9Jvj38jt5.png%2520align%3D%2522center%2522" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WIh9OW39--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1657760613270/9Jvj38jt5.png%2520align%3D%2522center%2522" alt="image.png" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Batch Lazy-Minting NFTs
&lt;/h2&gt;

&lt;p&gt;In the Signature Drop contract, we &lt;strong&gt;lazy-mint&lt;/strong&gt; all of our NFTs by uploading the metadata using the Batch Upload feature.&lt;/p&gt;

&lt;p&gt;Click the &lt;code&gt;Batch Upload&lt;/code&gt; button to get started.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4rZCn6wO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1657761823467/mUK8ouWOn.png%2520align%3D%2522center%2522" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4rZCn6wO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1657761823467/mUK8ouWOn.png%2520align%3D%2522center%2522" alt="image.png" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here, you'll be taken to a page where you can drag and drop your metadata and assets to upload them. You can use the example CSV and JSON files from the links on this page, or below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.thirdweb.com/example.csv"&gt;CSV Example File&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.thirdweb.com/example.json"&gt;JSON Example FIle&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is a preview of mine:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zKf9GLaw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1657761972229/1JWKm4fYn.png%2520align%3D%2522center%2522" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zKf9GLaw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1657761972229/1JWKm4fYn.png%2520align%3D%2522center%2522" alt="image.png" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you've prepared the files, drag them all into the upload box on the dashboard:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Yt9wSg2j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1657762030141/5eCE9x7dj.png%2520align%3D%2522center%2522" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Yt9wSg2j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1657762030141/5eCE9x7dj.png%2520align%3D%2522center%2522" alt="image.png" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This will allow you to preview your NFTs before lazy minting them.&lt;br&gt;
Ensure the properties and metadata appear how you expect, as you won't be able to modify them after they have been uploaded.&lt;/p&gt;

&lt;p&gt;Once you're happy, click &lt;code&gt;Next&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LnIwzMDW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1657762109425/IEV_q4REY.png%2520align%3D%2522center%2522" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LnIwzMDW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1657762109425/IEV_q4REY.png%2520align%3D%2522center%2522" alt="image.png" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can then choose if you want to add a &lt;a href="https://portal.thirdweb.com/advanced-features/delayed-reveal"&gt;delayed reveal&lt;/a&gt; for your NFTs. For this guide, we'll leave it as &lt;code&gt;Reveal upon mint&lt;/code&gt; and click &lt;strong&gt;Upload NFTs&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aP3UOnwD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1657762191886/c81S6MIgM.png%2520align%3D%2522center%2522" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aP3UOnwD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1657762191886/c81S6MIgM.png%2520align%3D%2522center%2522" alt="image.png" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Configuring A Claim Phase
&lt;/h2&gt;

&lt;p&gt;Claim phases are conditions that outline &lt;strong&gt;how&lt;/strong&gt;, &lt;strong&gt;when&lt;/strong&gt;, and &lt;strong&gt;who&lt;/strong&gt; can claim NFTs from your collection; such as an allowlist, release date, or &lt;a href="https://portal.thirdweb.com/advanced-features/delayed-reveal"&gt;delayed reveal&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To add a claim phase, click the &lt;code&gt;Claim Phases&lt;/code&gt; tab and then the &lt;code&gt;Add Claim Phase&lt;/code&gt; button:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0XScYFw8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1657760834325/UXHSvXkPm.png%2520align%3D%2522center%2522" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0XScYFw8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1657760834325/UXHSvXkPm.png%2520align%3D%2522center%2522" alt="image.png" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's where we can configure who can claim from this drop. I'm going to set the :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;How much do you want to charge to claim the NFTs?&lt;/code&gt; to be &lt;code&gt;0.01&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;How many NFTs can be claimed per transaction?&lt;/code&gt; to be &lt;code&gt;1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;How many seconds do wallets have to wait in-between claiming?&lt;/code&gt; to be &lt;code&gt;Unlimited&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UnnNuc5O--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1657761119847/2ghOIC2ug.png%2520align%3D%2522center%2522" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UnnNuc5O--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1657761119847/2ghOIC2ug.png%2520align%3D%2522center%2522" alt="image.png" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you're happy, click &lt;code&gt;Save Claim Phases&lt;/code&gt;!&lt;/p&gt;
&lt;h2&gt;
  
  
  Setting Up the project
&lt;/h2&gt;

&lt;p&gt;We'll be using the &lt;a href="https://portal.thirdweb.com/thirdweb-deploy/thirdweb-cli"&gt;thirdweb CLI&lt;/a&gt; to initialize our application using Next.js and TypeScript.&lt;/p&gt;

&lt;p&gt;To create a new project using the CLI, run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx thirdweb create
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Give your application a name and the project will be initialized for us! Let's open the project up in a text editor now, I'll be using VS Code.&lt;/p&gt;

&lt;p&gt;I'll be using the styles available in the &lt;a href="https://github.com/thirdweb-example/signature-drop/tree/main/styles"&gt;source code&lt;/a&gt;,&lt;br&gt;
feel free to copy these files into your project if you want to use the same styles.&lt;/p&gt;

&lt;p&gt;If we take a look at our &lt;code&gt;pages/app.tsx&lt;/code&gt; file, we have a configured &lt;code&gt;activeChainId&lt;/code&gt; as &lt;code&gt;Mainnet&lt;/code&gt; which is Ethereum Mainnet.&lt;/p&gt;

&lt;p&gt;Since we deployed our contract on the Arbitrum Test network let's change it to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// This is the chainId your dApp will work on.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;activeChainId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ChainId&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ArbitrumTestnet&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Connecting to our contract
&lt;/h2&gt;

&lt;p&gt;Now we're ready to interact with our signature drop smart contract from within our code, to do that, we'll use the &lt;a href="https://portal.thirdweb.com/react/react.usesignaturedrop?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=signature-drop"&gt;useSignatureDrop&lt;/a&gt; hook from the React SDK.&lt;/p&gt;

&lt;p&gt;On the &lt;code&gt;index.tsx&lt;/code&gt; page:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;signatureDrop&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useSignatureDrop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0xBdEa6C9B18843cEA8262ead23767737512e452bC&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can get your contract address from the dashboard:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2Xsg8MkF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1657763367349/HUYsenavI.png%2520align%3D%2522center%2522" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2Xsg8MkF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1657763367349/HUYsenavI.png%2520align%3D%2522center%2522" alt="image.png" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Claiming NFTs
&lt;/h2&gt;

&lt;p&gt;Since the wallet connection logic is already configured inside our application thanks to the thirdweb CLI, here's how our page looks now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Home&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NextPage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useAddress&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;connectWithMetamask&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useMetamask&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;disconnectWallet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useDisconnect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;signatureDrop&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useSignatureDrop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0xBdEa6C9B18843cEA8262ead23767737512e452bC&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;disconnectWallet&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Disconnect Wallet&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Your address: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;connectWithMetamask&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Connect with Metamask&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Home&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The React SDK automatically uses the signer of the connected wallet when a user wants to perform an action on our smart contract such as &lt;code&gt;claim&lt;/code&gt; an NFT.&lt;/p&gt;

&lt;p&gt;Let's write the logic for that now. Firstly, the &lt;code&gt;claim&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;claim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;signatureDrop&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;claim&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And attach this function to a button:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;claim&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Claim&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we preview our application by running &lt;code&gt;yarn dev&lt;/code&gt; from the terminal and visit &lt;a href="http://localhost:3000/"&gt;http://localhost:3000/&lt;/a&gt; we can see our claim button:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ja3JagcS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1657763880415/92oE6VCnc.png%2520align%3D%2522center%2522" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ja3JagcS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1657763880415/92oE6VCnc.png%2520align%3D%2522center%2522" alt="image.png" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you click the &lt;code&gt;Claim&lt;/code&gt; button and approve the transaction, you can successfully mint the first NFT from the drop.&lt;/p&gt;

&lt;p&gt;Now in the dashboard, we have a &lt;strong&gt;Claimed Supply&lt;/strong&gt; of &lt;code&gt;1&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;That is the very basics of our minting page setup!&lt;/p&gt;

&lt;h2&gt;
  
  
  Claiming With Signature
&lt;/h2&gt;

&lt;p&gt;The signature drop contract also allows users to claim using a signature generated by an admin wallet. This is a three-step process:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;User requests a mint signature.&lt;/li&gt;
&lt;li&gt;Admin wallet (on the server) approves (or denies) the claim request of the user based on any criteria the admin chooses and sends back a mint signature when they approve.&lt;/li&gt;
&lt;li&gt;User uses the mint signature to claim NFTs from the signature drop.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1UQP5omq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1657771599960/zD2KaWxl1.png%2520align%3D%2522center%2522" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1UQP5omq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1657771599960/zD2KaWxl1.png%2520align%3D%2522center%2522" alt="image.png" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This enables all kinds of possibilities for us, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Restrictions of who can claim based on off-chain data&lt;/li&gt;
&lt;li&gt;Discounts for users who meet some criteria (such as owning another NFT, or being part of a Discord server)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We're going to check if the wallet owns one of our thirdweb &lt;a href="https://opensea.io/collection/thirdweb-community"&gt;Early Access Card NFTs&lt;/a&gt; and offer them a free mint if they do!&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating the API Route
&lt;/h3&gt;

&lt;p&gt;Let's go back to our code, and under the &lt;code&gt;pages&lt;/code&gt; folder, create an &lt;code&gt;api&lt;/code&gt; folder. Within it, create a file called &lt;code&gt;generate-mint-signature.ts&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let's firstly create the basic structure of our API route:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ThirdwebSDK&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@thirdweb-dev/sdk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NextApiRequest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;NextApiResponse&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;next&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;generateMintSignature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NextApiRequest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NextApiResponse&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// De-construct body from request&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;address&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Next code snippet here&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we call this API endpoint, we'll be passing an &lt;code&gt;address&lt;/code&gt; argument into the request body. In this API route, we de-structure that value so that we can use it when we generate the mint signature.&lt;/p&gt;

&lt;p&gt;Since we're going to provide the NFTs for free to wallets that own one of thirdweb's &lt;a href="https://opensea.io/collection/thirdweb-community"&gt;Early Access NFTs&lt;/a&gt;, let's check that now.&lt;/p&gt;

&lt;p&gt;To do that, we instantiate the thirdweb SDK with a read-only connection on the Polygon network and get the &lt;code&gt;thirdweb-community&lt;/code&gt; NFT Collection using its contract address.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Get the Early Access NFT Edition Drop contract&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;polygonSDK&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;ThirdwebSDK&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;polygon&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;earlyAccessNfts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;polygonSDK&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getEditionDrop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0xa9e893cc12026a2f6bd826fdb295eac9c18a7e88&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// this is the thirdweb-community NFT Collection address.&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we can use the &lt;code&gt;balanceOf&lt;/code&gt; function to check if the wallet that made this API request has any NFTs from that collection. Since it's an ERC-1155 collection, we check to see if they have a &lt;code&gt;balanceOf&lt;/code&gt; &lt;strong&gt;any&lt;/strong&gt; of the tokens in that collection in a loop:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Check to see if the wallet address has an early access NFT&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;numTokensInCollection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;earlyAccessNfts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getTotalCount&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;userHasToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// Check each token in the Edition Drop&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;numTokensInCollection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toNumber&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// See if they have the token&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;earlyAccessNfts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;balanceOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toNumber&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;userHasToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Great! Now we have a &lt;code&gt;userHasToken&lt;/code&gt; variable that is true &lt;em&gt;if&lt;/em&gt; the user had a balance greater than zero for any token in that ERC-1155 NFT Collection.&lt;/p&gt;

&lt;p&gt;Now we can use that variable to determine whether or not we generate a mint signature for this user:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="c1"&gt;// Now use the SDK on Goerli to get the signature drop&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;arbitrumSDK&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ThirdwebSDK&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fromPrivateKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PRIVATE_KEY&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;arbitrum-testnet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;signatureDrop&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;arbitrumSDK&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getSignatureDrop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;your-contract-address-here&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="c1"&gt;// Your contract address here&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// If the user has an early access NFT, generate a mint signature&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userHasToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mintSignature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;signatureDrop&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Can only be minted by the address we checked earlier&lt;/span&gt;
      &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Free!&lt;/span&gt;
      &lt;span class="na"&gt;mintStartTime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;// now&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mintSignature&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;User does not have an early access NFT&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above snippet, we are using our private key to instantiate the SDK on behalf of our admin wallet.&lt;/p&gt;

&lt;p&gt;Learn how to &lt;a href="https://portal.thirdweb.com/guides/create-a-metamask-wallet#export-your-private-key?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=signature-drop"&gt;export your private key&lt;/a&gt; from your wallet.&lt;/p&gt;

&lt;p&gt;To do this, create a file called &lt;code&gt;.env&lt;/code&gt; at the root of your project, and add the following to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PRIVATE_KEY=your-private-key-here
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Ensure you store and access your private key securely.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Using the API Route on the Front-end
&lt;/h3&gt;

&lt;p&gt;On our home page, we need a way to call our API route, let's write that function now.&lt;/p&gt;

&lt;p&gt;Here, we check to see if the mint signature came back from the API request. If it didn't, we display an error message. If it did, we call the&lt;br&gt;
&lt;code&gt;signature.mint&lt;/code&gt; with the mint signature to claim the NFT.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;claimWithSignature&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;signedPayloadReq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/api/generate-mint-signature`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;signedPayloadReq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Looks like you don't own an early access NFT :( You don't qualify for the free mint.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;signedPayload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;signedPayloadReq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;SignedPayload721WithQuantitySignature&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;signedPayload&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nft&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;signatureDrop&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;signedPayload&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="nx"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Succesfully minted NFT!`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now all we need to do is add a new button that calls this function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;claimWithSignature&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Claim&lt;/span&gt; &lt;span class="nx"&gt;Free&lt;/span&gt; &lt;span class="kd"&gt;with&lt;/span&gt; &lt;span class="nx"&gt;signature&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's test it out:&lt;/p&gt;

&lt;p&gt;On a wallet that &lt;strong&gt;doesn't&lt;/strong&gt; own one of these Early Access NFTs, the mint signature is not granted to them, meaning they are unable to mint for free using the signature minting method:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--p4kKldij--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1657866182974/CUcMmHkNJ.png%2520align%3D%2522center%2522" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--p4kKldij--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1657866182974/CUcMmHkNJ.png%2520align%3D%2522center%2522" alt="image.png" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On a wallet that &lt;strong&gt;does&lt;/strong&gt; own the Early Access NFTs, they are allowed to mint an NFT for free rather than paying with the regular claim method!&lt;/p&gt;

&lt;p&gt;Once the transaction is confirmed, we should see:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--F_mi05lx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1657866716782/U1Tm9cOL9.png%2520align%3D%2522center%2522" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--F_mi05lx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1657866716782/U1Tm9cOL9.png%2520align%3D%2522center%2522" alt="image.png" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;That's it! You have successfully created your very own ERC-721A NFT collection with signature minting, and built an app to claim your NFTs on top of it!&lt;/p&gt;

&lt;p&gt;To learn more about what you can do with the signature drop contract, check out the &lt;a href="https://portal.thirdweb.com/pre-built-contracts/signature-drop"&gt;Portal documentation&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>web3</category>
      <category>tutorial</category>
      <category>typescript</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>Create a dynamic allowlist with Airtable and Next.js</title>
      <dc:creator>Avneesh Agarwal</dc:creator>
      <pubDate>Thu, 28 Apr 2022 15:38:00 +0000</pubDate>
      <link>https://forem.com/thirdweb/create-a-dynamic-allowlist-with-airtable-and-nextjs-4c13</link>
      <guid>https://forem.com/thirdweb/create-a-dynamic-allowlist-with-airtable-and-nextjs-4c13</guid>
      <description>&lt;h2&gt;
  
  
  What is thirdweb?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://thirdweb.com/?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=dynamic_allowlist_edition" rel="noopener noreferrer"&gt;thirdweb&lt;/a&gt; is a platform that lets you deploy smart contracts without having to know Solidity, you can do it by using TypeScript, Python or Go or even without writing any code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In this guide, we are going to create an edition where people will be able to sign up their wallets to an allowlist and those wallets can later mint the NFT!&lt;/p&gt;

&lt;p&gt;Sounds cool, right!? Let's get started.&lt;/p&gt;

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

&lt;p&gt;I am going to use the &lt;a href="https://github.com/thirdweb-example/next-typescript-starter" rel="noopener noreferrer"&gt;Next typescript starter template of thirdweb&lt;/a&gt; for this guide. If you already have a Next.js app you can simply follow these steps to get started:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install &lt;code&gt;@thirdweb-dev/react&lt;/code&gt; and &lt;code&gt;@thirdweb-dev/sdk&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Add metamask authentication to the site. You can follow this &lt;a href="https://dev.to/guides/add-connectwallet-to-your-website"&gt;guide&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;You all are set to go now!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you are also going to use the &lt;a href="https://github.com/thirdweb-example/next-typescript-starter" rel="noopener noreferrer"&gt;Next TypeScript template&lt;/a&gt; then follow these steps&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click on the use template button in the repo&lt;/li&gt;
&lt;li&gt;Clone the repo&lt;/li&gt;
&lt;li&gt;Install the dependencies:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install # npm

yarn install # yarn
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default the network in &lt;code&gt;_app.tsx&lt;/code&gt; is Mainnet, we need to change it to Mumbai&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import type { AppProps } from 'next/app';
import { ChainId, ThirdwebProvider } from '@thirdweb-dev/react';

// This is the chainId your dApp will work on.
const activeChainId = ChainId.Mumbai;

function MyApp({ Component, pageProps }: AppProps) {
  return (
    &amp;lt;ThirdwebProvider desiredChainId={activeChainId}&amp;gt;
      &amp;lt;Component {...pageProps} /&amp;gt;
    &amp;lt;/ThirdwebProvider&amp;gt;
  );
}

export default MyApp;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating an edition and NFT
&lt;/h2&gt;

&lt;p&gt;We also need to create an edition and an NFT inside of the edition to be able to mint them to the users. So, go to the &lt;a href="https://thirdweb.com/dashboard?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=dynamic_allowlist_edition" rel="noopener noreferrer"&gt;thirdweb dashboard&lt;/a&gt; and create an edition. I am doing it with an Edition contract for this demo but it can be also done with one of one NFTs (ERC-721).&lt;/p&gt;

&lt;p&gt;Fill out the details and deploy the contract!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fportal.thirdweb.com%2Fassets%2Fportal%2Fguides%2Fdynamic-allowlist-edition%2Fdeploy-edition-contract.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%2Fportal.thirdweb.com%2Fassets%2Fportal%2Fguides%2Fdynamic-allowlist-edition%2Fdeploy-edition-contract.png" alt="Deploy edition contract"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, let's create and mint a new NFT inside of it. Fill out the details and make sure to set the initial supply to 0.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fportal.thirdweb.com%2Fassets%2Fportal%2Fguides%2Fdynamic-allowlist-edition%2Fmint-new-nft.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%2Fportal.thirdweb.com%2Fassets%2Fportal%2Fguides%2Fdynamic-allowlist-edition%2Fmint-new-nft.png" alt="Mint New NFT"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Making the website
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Creating an nft card
&lt;/h3&gt;

&lt;p&gt;To showcase our nft, we are going to create a simple card and we will get the data from the edition contract itself! So, inside &lt;code&gt;index.tsx&lt;/code&gt; add the useEdition hook 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;const edition = useEdition("EDITION_CONTRACT_ADDRESS");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need to import it from the thirdweb sdk:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useEdition } from "@thirdweb-dev/react";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we are going to create a new state to hold the nft data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  const [nftData, setNftData] = useState&amp;lt;EditionMetadata["metadata"] | null&amp;gt;(
    null
  );
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We also need to import EditionMetadata and useState:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { EditionMetadata } from "@thirdweb-dev/sdk";
import { useState } from "react";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, create a useEffect to get the data from the contract and update the variable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; useEffect(() =&amp;gt; {
    edition?.get("0").then((nft) =&amp;gt; {
      setNftData(nft.metadata);
    });
  }, [edition]);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you console log the nft metadata you will get something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fportal.thirdweb.com%2Fassets%2Fportal%2Fguides%2Fdynamic-allowlist-edition%2Fnft-metadata.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%2Fportal.thirdweb.com%2Fassets%2Fportal%2Fguides%2Fdynamic-allowlist-edition%2Fnft-metadata.png" alt="NFT Metadata"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If the user is logged in we will show them this nft instead of there address, so replace the fragment &lt;code&gt;(&amp;lt;&amp;gt;)&lt;/code&gt; with this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div&amp;gt;
  {nftData?.image &amp;amp;&amp;amp; (
    &amp;lt;Image
      src={nftData?.image}
      alt={nftData?.name}
      width="280"
      height="210"
      objectFit="contain"
    /&amp;gt;
  )}
  &amp;lt;p&amp;gt;
    &amp;lt;span&amp;gt;Name:&amp;lt;/span&amp;gt; {nftData?.name}
  &amp;lt;/p&amp;gt;
  &amp;lt;p&amp;gt;
    &amp;lt;span&amp;gt; Description:&amp;lt;/span&amp;gt; {nftData?.description}
  &amp;lt;/p&amp;gt;

  &amp;lt;button&amp;gt;Mint&amp;lt;/button&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will now get an error because we are using the next &lt;code&gt;&amp;lt;Image /&amp;gt;&lt;/code&gt; component but haven't whitelisted the domain, so go to &lt;code&gt;next.config.js&lt;/code&gt; and add 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;/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
  images: {
    domains: ["gateway.ipfscdn.io"],
  },
};

module.exports = nextConfig;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since we are changing the next.js config we need to restart the server. Once you restart the server you will see something like this&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fportal.thirdweb.com%2Fassets%2Fportal%2Fguides%2Fdynamic-allowlist-edition%2Fnft-card-display.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%2Fportal.thirdweb.com%2Fassets%2Fportal%2Fguides%2Fdynamic-allowlist-edition%2Fnft-card-display.png" alt="NFT Card display"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating the mint api
&lt;/h3&gt;

&lt;p&gt;We are going to use the signature minting on our backend to ensure that the address is present in the airtable, but first let's get the signature minting working.&lt;/p&gt;

&lt;p&gt;Create a new folder &lt;code&gt;api&lt;/code&gt; in the pages folder and &lt;code&gt;generate-mint-sig.ts&lt;/code&gt; inside it.&lt;/p&gt;

&lt;p&gt;We will now build a basic api that will output "gm wagmi"&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import type { NextApiRequest, NextApiResponse } from "next";

const generateMintSignature = async (
  req: NextApiRequest,
  res: NextApiResponse
) =&amp;gt; {
  res.send("gm wagmi");
};

export default generateMintSignature;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates a basic api for us, if you now go to the &lt;a href="http://localhost:3000/api/generate-mint-sig" rel="noopener noreferrer"&gt;&lt;code&gt;api/generate-mint-sig&lt;/code&gt;&lt;/a&gt; endpoint you will get a response of &lt;code&gt;Gm wagmi&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fportal.thirdweb.com%2Fassets%2Fportal%2Fguides%2Fdynamic-allowlist-edition%2Fapi-response.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%2Fportal.thirdweb.com%2Fassets%2Fportal%2Fguides%2Fdynamic-allowlist-edition%2Fapi-response.png" alt="Api response"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's now initialize the thirdweb sdk!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const sdk = new ThirdwebSDK(
    new ethers.Wallet(
      process.env.PRIVATE_KEY as string,
      ethers.getDefaultProvider(process.env.ALCHEMY_API_URL)
    )
  );
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;as you can see we are using 2 environment variables to initialize the sdk. The first is the &lt;code&gt;PRIVATE_KEY&lt;/code&gt; which is the private key of the wallet. The second is the &lt;code&gt;ALCHEMY_API_URL&lt;/code&gt; which is the url of the Alchemy api. Create a new file &lt;code&gt;.env.local&lt;/code&gt; and add the two variables.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PRIVATE_KEY=&amp;lt;private_key&amp;gt;
ALCHEMY_API_URL=&amp;lt;alchemy_api_url&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's see how to get these two variables.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Getting the wallet private key&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In your metamask wallet, click on the three dots, then click account details. You will see an option to export private key there. Export your private key and paste it into the &lt;code&gt;PRIVATE_KEY&lt;/code&gt; variable.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fportal.thirdweb.com%2Fassets%2Fportal%2Fguides%2Fdynamic-allowlist-edition%2Fexport-pvt-key.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%2Fportal.thirdweb.com%2Fassets%2Fportal%2Fguides%2Fdynamic-allowlist-edition%2Fexport-pvt-key.png" alt="Export private key"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This will give full access to your wallet to make sure to keep it secret!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Getting the alchemy api key&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Go to &lt;a href="https://dashboard.alchemyapi.io/" rel="noopener noreferrer"&gt;Alchemy&lt;/a&gt; and sign up for an account. You need to create a new app, so click on create app. Fill out the details, and hit submit. I am using Mumbai network for this demo but you need to use the network that you are using!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fportal.thirdweb.com%2Fassets%2Fportal%2Fguides%2Fdynamic-allowlist-edition%2Fcreate-alchemy-app.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%2Fportal.thirdweb.com%2Fassets%2Fportal%2Fguides%2Fdynamic-allowlist-edition%2Fcreate-alchemy-app.png" alt="Create Alchemy app"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, paste this in the &lt;code&gt;.env.local&lt;/code&gt; file too. Since we have changed the env variables we need to restart the server. So, cut the terminal and run &lt;code&gt;yarn dev&lt;/code&gt; again.&lt;/p&gt;

&lt;p&gt;We also need to import &lt;code&gt;ethers&lt;/code&gt; and &lt;code&gt;ThirdwebSDK&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;import { ThirdwebSDK } from "@thirdweb-dev/sdk";
import { ethers } from "ethers";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Generating the siganture mint&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In the api we are going to use the sdk to get access to the edition contract and generate a mint signature:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; const edition = sdk.getEdition("EDITION_CONTRACT_ADDRESS");
  try {
    const signedPayload = await edition.signature.generate({
      tokenId: 0,
      quantity: "1",
      to: address,
    });

    res.status(200).json({
      signedPayload: signedPayload,
    });
  } catch (err) {
    res.status(500).json({
      error: err,
    });
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will get the address from the frontend so, add this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const { address } = JSON.parse(req.body);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's now mint the api on the frontend by calling this api:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  const mintWithSignature = async () =&amp;gt; {
    const signedPayloadReq = await fetch(`/api/generate-mint-sig`, {
      method: "POST",
      body: JSON.stringify({ address }),
    });

    const signedPayload = await signedPayloadReq.json();

    try {
      const nft = await edition?.signature.mint(signedPayload.signedPayload);
      return nft;
    } catch (err) {
      console.error(err);
      return null;
    }
  };
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function will request the api that we just built with the address. It will give us a signed payload that we can use to mint the nft via our edition contract. So, let's attach it to the button:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;button onClick={() =&amp;gt; mintWithSignature()}&amp;gt;Mint&amp;lt;/button&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now our mint works! But wait, everyone can mint now so let's create an airtable database to store the addresses that can mint.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating an allowlist with airtable
&lt;/h2&gt;

&lt;p&gt;Go to &lt;a href="https://airtable.com/" rel="noopener noreferrer"&gt;Airtable&lt;/a&gt; and create a new base.&lt;/p&gt;

&lt;p&gt;After you create a new base, give a name to your base and add two columns: &lt;code&gt;Address&lt;/code&gt; and &lt;code&gt;Minted&lt;/code&gt; like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fportal.thirdweb.com%2Fassets%2Fportal%2Fguides%2Fdynamic-allowlist-edition%2Fairtable-new-base.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%2Fportal.thirdweb.com%2Fassets%2Fportal%2Fguides%2Fdynamic-allowlist-edition%2Fairtable-new-base.png" alt="Airtable base"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Getting airtable api keys and id&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We now need to get some api key's and id's to interact with the base. So, go to &lt;a href="https://airtable.com/account" rel="noopener noreferrer"&gt;your Airtable account&lt;/a&gt; and generate an api key&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fportal.thirdweb.com%2Fassets%2Fportal%2Fguides%2Fdynamic-allowlist-edition%2Fgenerate-api-key-airtable.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%2Fportal.thirdweb.com%2Fassets%2Fportal%2Fguides%2Fdynamic-allowlist-edition%2Fgenerate-api-key-airtable.png" alt="Generate api key"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Store this api key somewhere safe as we are going to need it.&lt;/p&gt;

&lt;p&gt;Now to get the base id go to the &lt;a href="https://airtable.com/api" rel="noopener noreferrer"&gt;Airtable API&lt;/a&gt; and click on the base that you just created. When you open the page, at the top itself you would see "Your base id is app......".&lt;/p&gt;

&lt;p&gt;Inside &lt;code&gt;.env.local&lt;/code&gt; add three new variables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AIRTABLE_API_KEY=
AIRTABLE_BASE_ID=
AIRTABLE_TABLE_NAME=
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Creating a utility function for accessing the table
&lt;/h3&gt;

&lt;p&gt;To keep our code clean we are going to create a file where we initialize the airtable with the api key, name, and id. So, create a new folder &lt;code&gt;utils&lt;/code&gt; and &lt;code&gt;Airtable.ts&lt;/code&gt; inside it. Now, add in the following in &lt;code&gt;Airtable.ts&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;import Airtable from "airtable";

// Authenticate
Airtable.configure({
  apiKey: process.env.AIRTABLE_API_KEY,
});

// Initialize a base
const base = Airtable.base(process.env.AIRTABLE_BASE_ID!);

// Reference a table
const table = base(process.env.AIRTABLE_TABLE_NAME!);

export { table };
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see we are going to need to install a new package called &lt;code&gt;airtable&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i airtable &lt;span class="c"&gt;# npm&lt;/span&gt;

yarn add airtable &lt;span class="c"&gt;# yarn&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we need to update the api to first check if the wallet is present in the table. So, in &lt;code&gt;api/generate-mint-sig.ts&lt;/code&gt; add 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;  const record = await table
    .select({
      fields: ["Addresses", "minted"],
      filterByFormula: `NOT({Addresses} != '${address}')`,
    })
    .all();

  if (record.length === 0) {
    res.status(404).json({
      error: "User isn't in allowlist",
    });
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, this queries the airtable to get the records of the address present in the addresses column and we are checking if the length record is 0. If it is 0, then we are not allowing the user to mint and send an error. We will also wrap the part where we send the response in an else block. The api should now look similar to this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import type { NextApiRequest, NextApiResponse } from "next";
import { ThirdwebSDK } from "@thirdweb-dev/sdk";
import { ethers } from "ethers";
import { table } from "../../utils/Airtable";

const generateMintSignature = async (
  req: NextApiRequest,
  res: NextApiResponse
) =&amp;gt; {
  const { address } = JSON.parse(req.body);

  const record = await table
    .select({
      fields: ["Addresses", "minted"],
      filterByFormula: `NOT({Addresses} != '${address}')`,
    })
    .all();

  if (record.length === 0) {
    res.status(404).json({
      error: "User isn't in allowlist",
    });
  } else {
    const sdk = new ThirdwebSDK(
      new ethers.Wallet(
        process.env.PRIVATE_KEY as string,
        ethers.getDefaultProvider(process.env.ALCHEMY_API_URL)
      )
    );

    const edition = sdk.getEdition(
      "0x62C84CC051544c43d05a5Ff0E8Da596fBdB15032"
    );
    try {
      const signedPayload = await edition.signature.generate({
        tokenId: 0,
        quantity: "1",
        to: address,
      });

      res.status(200).json({
        signedPayload: signedPayload,
      });
    } catch (err) {
      res.status(500).json({
        error: err,
      });
    }
  }
};

export default generateMintSignature;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the mintWithSignature function we will now add a simple alert to show the error if the user is not in the allowlist.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; const mintWithSignature = async () =&amp;gt; {
    const signedPayloadReq = await fetch(`/api/generate-mint-sig`, {
      method: "POST",
      body: JSON.stringify({ address }),
    });

    const signedPayload = await signedPayloadReq.json();

    if (signedPayload.error) {
      alert(signedPayload.error);
      return;
    }

    try {
      const nft = await edition?.signature.mint(signedPayload.signedPayload);
      return nft;
    } catch (err) {
      console.error(err);
      return null;
    }
  };
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now if you try minting you should now see an error that you are not in the allowlist. But if you add the address you are using to mint to the address column, it would allow you to mint!&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting the minted to true when the address mints
&lt;/h3&gt;

&lt;p&gt;We will create another api to not expose the api keys, so in the &lt;code&gt;api&lt;/code&gt; folder create a new file &lt;code&gt;set-minted.ts&lt;/code&gt; and add 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;import type { NextApiRequest, NextApiResponse } from "next";
import { table } from "../../utils/Airtable";

const generateMintSignature = async (
  req: NextApiRequest,
  res: NextApiResponse
) =&amp;gt; {
  const { address } = JSON.parse(req.body);

  const record = await table
    .select({
      fields: ["Addresses", "minted"],
      filterByFormula: `NOT({Addresses} != '${address}')`,
    })
    .all();

  try {
    record[0].updateFields({
      minted: "true",
    });
    res.status(200).json({
      success: true,
    });
  } catch (err) {
    res.status(500).json({
      error: err,
    });
  }
};

export default generateMintSignature;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Basically what this code block is doing is getting the record of the address and then updating the minted column to true. And for basic error handling if there is an error we will return the error. Now, in the mintSignature function I will add the fetch request to the &lt;code&gt;set-minted&lt;/code&gt; api if the nft was minted successful 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;if (nft) {
  await fetch(`/api/set-minted`, {
    method: "POST",
    body: JSON.stringify({ address }),
  });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you try minting again and check the airtable it would now set the minted column to true! If you get an error like the column name not found then make sure that the names are same.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding users to allowlist
&lt;/h2&gt;

&lt;p&gt;I am going to add a simple button for adding users to allowlist. You can even create an early access form or something similar. So, create a button in &lt;code&gt;index.tsx&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;&amp;lt;button&amp;gt;Add wallet to allowlist&amp;lt;/button&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let's create an api to add the wallet to the allowlist. So, create a new file &lt;code&gt;add-to-allowlist.ts&lt;/code&gt; and add 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;import type { NextApiRequest, NextApiResponse } from "next";
import { table } from "../../utils/Airtable";

const addToAllowlist = async (req: NextApiRequest, res: NextApiResponse) =&amp;gt; {
  const { address } = JSON.parse(req.body);

  const record = await table
    .select({
      fields: ["Addresses", "minted"],
      filterByFormula: `NOT({Addresses} != '${address}')`,
    })
    .all();

  if (record.length &amp;gt; 0) {
    res.status(400).json({
      success: false,
      error: "User is already in allowlist",
    });
  }

  if (record.length === 0) {
    try {
      await table.create([
        {
          fields: {
            Addresses: address,
          },
        },
      ]);
      res.status(200).json({
        success: true,
        message: "User added to allowlist",
      });
    } catch (err) {
      res.status(500).json({
        success: false,
        error: err,
      });
    }
  }
};

export default addToAllowlist;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we are first checking if the user already exists and if it exists we will return an error saying that the user is already in the allowlist. If the user doesn't exist we will create the user in the allowlist. Now, let's head back to the frontend code and create a function to call this api:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  const addWallet = async () =&amp;gt; {
    const payload = await fetch(`/api/add-to-allowlist`, {
      method: "POST",
      body: JSON.stringify({ address }),
    });

    const payloadJson = await payload.json();
    console.log(payloadJson);

    if (payloadJson.success) {
      alert(payloadJson.message);
    } else {
      alert(payloadJson.error);
    }
  };
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, add an onClick event to the button:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;button onClick={addWallet}&amp;gt;Add wallet to allowlist&amp;lt;/button&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you try switching the connected wallet or remove the wallet from the database you will see that the user's wallet address is being added to the base!&lt;/p&gt;

&lt;h2&gt;
  
  
  Minor improvements (Optional)
&lt;/h2&gt;

&lt;p&gt;Let's just add some minor improvements to our app!&lt;/p&gt;

&lt;h3&gt;
  
  
  Styling
&lt;/h3&gt;

&lt;p&gt;Currently the site looks pretty boring, so let's add some simple styling. Create a new file &lt;code&gt;globals.css&lt;/code&gt; in the &lt;code&gt;styles&lt;/code&gt; folder and add the following to reset the styles:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;html,
body {
  padding: 0;
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
    Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
}

a {
  color: inherit;
  text-decoration: none;
}

* {
  box-sizing: border-box;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Import it in the _app.tsx file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import "../styles/globals.css";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, create a new file &lt;code&gt;Home.module.css&lt;/code&gt; in the &lt;code&gt;styles&lt;/code&gt; folder and add these simple stylings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.container {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100vh;
  background-color: #c0ffee;
}

.container &amp;gt; button,
.btn {
  background: #1ce;
  color: #fff;
  font-size: 1rem;
  padding: 0.5rem 1rem;
  border: none;
  border-radius: 0.5rem;
  cursor: pointer;
}

.btn {
  margin-top: 10px;
}

.NFT {
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.nftDesc {
  margin: 10px 0px;
  font-size: 0.8rem;
  color: #000;
}

.nftDesc &amp;gt; span {
  font-weight: bold;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's implement these stylings in &lt;code&gt;index.tsx&lt;/code&gt; by adding the classNames:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; &amp;lt;div className={styles.container}&amp;gt;
      {address ? (
        &amp;lt;div className={styles.NFT}&amp;gt;
          {nftData?.image &amp;amp;&amp;amp; (
            &amp;lt;Image
              src={nftData?.image}
              alt={nftData?.name}
              width="280"
              height="210"
              objectFit="contain"
            /&amp;gt;
          )}
          &amp;lt;p className={styles.nftDesc}&amp;gt;
            &amp;lt;span&amp;gt;Name:&amp;lt;/span&amp;gt; {nftData?.name}
          &amp;lt;/p&amp;gt;
          &amp;lt;p className={styles.nftDesc}&amp;gt;
            &amp;lt;span&amp;gt; Description:&amp;lt;/span&amp;gt; {nftData?.description}
          &amp;lt;/p&amp;gt;

          &amp;lt;button className={styles.btn} onClick={addWallet}&amp;gt;
            Add wallet to allowlist
          &amp;lt;/button&amp;gt;

          &amp;lt;button className={styles.btn} onClick={() =&amp;gt; mintWithSignature()}&amp;gt;
            Mint
          &amp;lt;/button&amp;gt;
        &amp;lt;/div&amp;gt;
      ) : (
        &amp;lt;button onClick={connectWithMetamask}&amp;gt;Connect with Metamask&amp;lt;/button&amp;gt;
      )}
    &amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our website now looks much better!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fportal.thirdweb.com%2Fassets%2Fportal%2Fguides%2Fdynamic-allowlist-edition%2Fwebsite-preview.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%2Fportal.thirdweb.com%2Fassets%2Fportal%2Fguides%2Fdynamic-allowlist-edition%2Fwebsite-preview.png" alt="Deploy edition contract"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Loading
&lt;/h3&gt;

&lt;p&gt;Currently if you click the mint button or add to allowlist button nothing happens for a while, so let's add a loading text to tell the user that something is happening. So, create 2 states in the &lt;code&gt;Home.tsx&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const [addWalletLoading, setAddWalletLoading] = useState(false);
const [mintLoading, setMintLoading] = useState(false);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add this ternary operator for changing the text of the buttons and disable the button if it is loading:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; &amp;lt;button
   className={styles.btn}
   disabled={addWalletLoading}
   onClick={addWallet}
&amp;gt;
  {addWalletLoading ? "loading..." : "Add wallet to allowlist"}
&amp;lt;/button&amp;gt;

 &amp;lt;button
   className={styles.btn}
   disabled={mintLoading}
   onClick={() =&amp;gt; mintWithSignature()}
&amp;gt;
  {mintLoading ? "loading..." : "Mint"}
&amp;lt;/button&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nothing happens yet because we aren't changing the states so, in the functions we need to change the loading states:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  const mintWithSignature = async () =&amp;gt; {
    setMintLoading(true);
    const signedPayloadReq = await fetch(`/api/generate-mint-sig`, {
      method: "POST",
      body: JSON.stringify({ address }),
    });

    const signedPayload = await signedPayloadReq.json();

    if (signedPayload.error) {
      alert(signedPayload.error);
      return;
    }

    try {
      const nft = await edition?.signature.mint(signedPayload.signedPayload);
      if (nft) {
        await fetch(`/api/set-minted`, {
          method: "POST",
          body: JSON.stringify({ address }),
        });
      }
      return nft;
    } catch (err) {
      console.error(err);
      return null;
    } finally {
      setMintLoading(false);
    }
  };

  const addWallet = async () =&amp;gt; {
    setAddWalletLoading(true);
    const payload = await fetch(`/api/add-to-allowlist`, {
      method: "POST",
      body: JSON.stringify({ address }),
    });

    const payloadJson = await payload.json();
    setAddWalletLoading(false);

    if (payloadJson.success) {
      alert(payloadJson.message);
    } else {
      alert(payloadJson.error);
    }
  };
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you now try to click any of the buttons you would see the loading text for a second.&lt;/p&gt;

&lt;h3&gt;
  
  
  Error handling
&lt;/h3&gt;

&lt;p&gt;Currently, the user can be on the wrong network and get weird errors, so we will disable the button if the user is not on the correct network.&lt;/p&gt;

&lt;p&gt;Get access to the network by using the &lt;code&gt;useNetwork&lt;/code&gt; hook:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const network = useNetwork();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will be imported from the thirdweb sdk:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import {
  useAddress,
  useEdition,
  useMetamask,
  useNetwork,
} from "@thirdweb-dev/react";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, in the mint button add the checks-&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;button
  className={styles.btn}
  disabled={mintLoading || network[0]?.data?.chain?.id !== ChainId.Mumbai}
  onClick={() =&amp;gt; mintWithSignature()}
&amp;gt;
  {network[0]?.data?.chain?.id === ChainId.Mumbai
    ? mintLoading
      ? "loading..."
      : "Mint"
    : "Switch to Mumbai"}
&amp;lt;/button&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I built this Dapp on the Mumbai network so I am checking for the Mumbai network but you need to do this for the network you built upon.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This was a lot, now give yourself a pat on the back and share your amazing apps with us! If you want to have a look at the code, check out the &lt;a href="https://github.com/thirdweb-dev/examples/tree/main/typescript/claim-button-react" rel="noopener noreferrer"&gt;GitHub Repository&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>web3</category>
      <category>nextjs</category>
      <category>nft</category>
      <category>thirdweb</category>
    </item>
    <item>
      <title>Sell your NFT in multiple currencies at the same time</title>
      <dc:creator>Avneesh Agarwal</dc:creator>
      <pubDate>Tue, 19 Apr 2022 14:56:07 +0000</pubDate>
      <link>https://forem.com/thirdweb/sell-your-nft-in-multiple-currencies-at-the-same-time-2def</link>
      <guid>https://forem.com/thirdweb/sell-your-nft-in-multiple-currencies-at-the-same-time-2def</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In this guide, we are going to create an edition collection that will allow users to buy an NFT in multiple currencies. All this is going to happen with Next.js and thirdweb. We are going to use the signature-based mint feature of thirdweb.&lt;/p&gt;

&lt;p&gt;Sounds cool, right!? Let's get started.&lt;/p&gt;

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

&lt;p&gt;I am going to use the &lt;a href="https://github.com/thirdweb-example/next-typescript-starter"&gt;Next typescript starter template of thirdweb&lt;/a&gt; for this guide. If you already have a Next.js app you can simply follow these steps to get started-&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install &lt;code&gt;@thirdweb-dev/react&lt;/code&gt; and &lt;code&gt;@thirdweb-dev/sdk&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Add metamask authentication to the site. You can follow this &lt;a href="https://portal.thirdweb.com/guides/add-connectwallet-to-your-website?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=sell_nft_multiple_currencies"&gt;guide&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;You all are set to go now!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you are also going to use the &lt;a href="https://github.com/thirdweb-example/next-typescript-starter"&gt;Next TypeScript template&lt;/a&gt; then follow these steps&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click on the use template button in the repo&lt;/li&gt;
&lt;li&gt;Clone the repo&lt;/li&gt;
&lt;li&gt;Install the dependencies:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="c"&gt;# npm&lt;/span&gt;

yarn &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="c"&gt;# yarn&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;By default the network in &lt;code&gt;_app.tsx&lt;/code&gt; is Mainnet, we need to change it to Mumbai&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AppProps&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next/app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ChainId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ThirdwebProvider&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@thirdweb-dev/react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// This is the chainId your dApp will work on.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;activeChainId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ChainId&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Mumbai&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;MyApp&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pageProps&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;AppProps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ThirdwebProvider&lt;/span&gt; &lt;span class="na"&gt;desiredChainId&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;activeChainId&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Component&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;pageProps&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;ThirdwebProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;MyApp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Creating an edition and NFT
&lt;/h2&gt;

&lt;p&gt;We also need to create an edition and an NFT inside of the edition to be able to mint them to the users. So, go to the &lt;a href="https://thirdweb.com/dashboard?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=sell_nft_multiple_currencies"&gt;thirdweb dashboard&lt;/a&gt; and create an edition.&lt;/p&gt;

&lt;p&gt;Fill out the details and deploy the contract!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8VAarEhS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://portal.thirdweb.com/assets/portal/guides/sell-nft-multiple-currencies/deploy-edition-contract.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8VAarEhS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://portal.thirdweb.com/assets/portal/guides/sell-nft-multiple-currencies/deploy-edition-contract.png" alt="Deploy edition contract" width="880" height="605"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, let's create and mint a new NFT inside of it. Fill out the details and make sure to set the initial supply to 0.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lO0CiLZ5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://portal.thirdweb.com/assets/portal/guides/sell-nft-multiple-currencies/mint-new-nft.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lO0CiLZ5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://portal.thirdweb.com/assets/portal/guides/sell-nft-multiple-currencies/mint-new-nft.png" alt="Mint New NFT" width="846" height="997"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Building the NFT card
&lt;/h2&gt;

&lt;p&gt;I am going to create a simple card to display the NFT, which will have the name, and description of the NFT. A dropdown to be able to change the currency and a button to mint the NFT! At this point, your &lt;code&gt;pages/index.tsx&lt;/code&gt; file should look something like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useDisconnect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useMetamask&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@thirdweb-dev/react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NextPage&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;next&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Home&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NextPage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useAddress&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;connectWithMetamask&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useMetamask&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;disconnectWallet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useDisconnect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;disconnectWallet&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Disconnect Wallet&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Your address: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;connectWithMetamask&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Connect with Metamask&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Home&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Instead of showing the disconnect Wallet button and wallet address, we will now show the card instead. So, replace everything inside the fragment &lt;code&gt;(&amp;lt;&amp;gt;)&lt;/code&gt; with the following-&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;img&lt;/span&gt;
    &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;nft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ipfs://&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://ipfs.thirdweb.com/ipfs/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="na"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;nft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"200px"&lt;/span&gt;
    &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"100%"&lt;/span&gt;
  &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Name: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;nft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Description: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;nft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;select&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;nft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;option&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;option&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;select&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Mint&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You might be wondering where are we getting the NFT object, we are going to create a new file and store the NFT object there to keep our code clean. So, create a new file &lt;code&gt;nft.ts&lt;/code&gt; and add this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NATIVE_TOKEN_ADDRESS&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@thirdweb-dev/sdk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nft&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;My cool NFT&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;This is the description for my cool NFT&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ipfs://QmRdoPRtfb6MHLQgsBsC5WVDAf7BZijykYUefEmt6UrTTn/0.png&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MATIC&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NATIVE_TOKEN_ADDRESS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;USDC&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0xe11A86849d99F524cAC3E7A0Ec1241828e332C62&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Here, we are creating and exporting a new &lt;code&gt;nft&lt;/code&gt; object with some properties like name, description, image, etc. The tokens array will contain the different currencies using which we can mint the NFTs. You need to specify a name, address, and price for the token here. We are getting the &lt;code&gt;NATIVE_TOKEN_ADDRESS&lt;/code&gt; from the thirdweb package.&lt;/p&gt;

&lt;p&gt;Finally, import nft from this file in &lt;code&gt;index.tsx&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;nft&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../nft&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If you now go to &lt;a href="http://localhost:3000/"&gt;http://localhost:3000/&lt;/a&gt; you will be able to see a card like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pq6Y97x5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://portal.thirdweb.com/assets/portal/guides/sell-nft-multiple-currencies/nft-card.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pq6Y97x5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://portal.thirdweb.com/assets/portal/guides/sell-nft-multiple-currencies/nft-card.png" alt="NFT Card" width="880" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I haven't styled this so it doesn't look that beautiful but feel free to customize it for use and make it beautiful ;)!&lt;/p&gt;
&lt;h3&gt;
  
  
  Storing the currency
&lt;/h3&gt;

&lt;p&gt;We need to store the currency which the user has selected. So, we will create a new &lt;code&gt;state&lt;/code&gt; and change it every time the value of the dropdown changes. To do this use the &lt;code&gt;useState&lt;/code&gt; hook and pass in the initial value as &lt;code&gt;"MATIC"&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;tokenName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setTokenName&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MATIC&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;For updating it inside the &lt;code&gt;onChange&lt;/code&gt; event we will use the &lt;code&gt;setTokenName&lt;/code&gt; function.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;select&lt;/span&gt; &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setTokenName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;nft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;option&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;option&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;select&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This will now update the currency so we can use it in the minting process.&lt;/p&gt;
&lt;h3&gt;
  
  
  Creating an api for generating the signature
&lt;/h3&gt;

&lt;p&gt;Inside the &lt;code&gt;pages&lt;/code&gt; folder, create a new folder &lt;code&gt;api&lt;/code&gt; and &lt;code&gt;generate-mint-sig.ts&lt;/code&gt; inside it. We will create our whole api for generating the mint signature here!&lt;/p&gt;

&lt;p&gt;Let's start by building a basic api.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import type { NextApiRequest, NextApiResponse } from "next";

const generateMintSignature = async (
  req: NextApiRequest,
  res: NextApiResponse
) =&amp;gt; {
  res.send("Gm wagmi");
};

export default generateMintSignature;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This creates a basic api for us, if you now go to the &lt;a href="http://localhost:3000/api/generate-mint-sig"&gt;&lt;code&gt;api/generate-mint-sig&lt;/code&gt;&lt;/a&gt; endpoint you will get a response of &lt;code&gt;Gm wagmi&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--L8Xb6zp9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://portal.thirdweb.com/assets/portal/guides/sell-nft-multiple-currencies/api-response.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--L8Xb6zp9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://portal.thirdweb.com/assets/portal/guides/sell-nft-multiple-currencies/api-response.png" alt="Api response" width="780" height="397"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's now initialize the thirdweb sdk!&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sdk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;ThirdwebSDK&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Wallet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PRIVATE_KEY&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getDefaultProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ALCHEMY_API_URL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;as you can see we are using 2 environment variables to initialize the sdk. The first is the &lt;code&gt;PRIVATE_KEY&lt;/code&gt; which is the private key of the wallet. The second is the &lt;code&gt;ALCHEMY_API_URL&lt;/code&gt; which is the url of the Alchemy api. Create a new file &lt;code&gt;.env.local&lt;/code&gt; and add the two variables.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PRIVATE_KEY=&amp;lt;private_key&amp;gt;
ALCHEMY_API_URL=&amp;lt;alchemy_api_url&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Let's see how to get these two variables.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Getting the wallet private key&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In your metamask wallet, click on the three dots, then click account details. You will see an option to export private key there. Export your private key and paste it into the &lt;code&gt;PRIVATE_KEY&lt;/code&gt; variable.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--atpZ6tF_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://portal.thirdweb.com/assets/portal/guides/sell-nft-multiple-currencies/export-pvt-key.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--atpZ6tF_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://portal.thirdweb.com/assets/portal/guides/sell-nft-multiple-currencies/export-pvt-key.png" alt="Export private key" width="445" height="747"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This will give full access to your wallet to make sure to keep it secret!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Getting the alchemy api key&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Go to &lt;a href="https://dashboard.alchemyapi.io/"&gt;Alchemy&lt;/a&gt; and sign up for an account. You need to create a new app, so click on create app. Fill out the details, and hit submit. I am using Mumbai network for this demo but you need to use the network that you are using!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IiGBQXGF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://portal.thirdweb.com/assets/portal/guides/sell-nft-multiple-currencies/create-alchemy-app.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IiGBQXGF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://portal.thirdweb.com/assets/portal/guides/sell-nft-multiple-currencies/create-alchemy-app.png" alt="Create Alchemy app" width="880" height="443"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, paste this in the &lt;code&gt;.env.local&lt;/code&gt; file too. Since we have changed the env variables we need to restart the server. So, cut the terminal and run &lt;code&gt;yarn dev&lt;/code&gt; again.&lt;/p&gt;

&lt;p&gt;We also need to import &lt;code&gt;ethers&lt;/code&gt; and &lt;code&gt;ThirdwebSDK&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ThirdwebSDK&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@thirdweb-dev/sdk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ethers&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Generating the signature for mint
&lt;/h3&gt;

&lt;p&gt;From the frontend we will get the &lt;code&gt;tokenName&lt;/code&gt;, &lt;code&gt;tokenId&lt;/code&gt;, and the &lt;code&gt;address&lt;/code&gt; of the person we are going to mint the NFT to. I am only getting these parameters to make sure that people can't manipulate the data. So, get these parameters from the response body:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;tokenId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tokenName&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We also need access to the edition functions, so get the edition like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;edition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getEdition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;YOUR_EDITION_ADDRESS&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We can now use this to generate a mint signature. So, add in this try/catch block:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;signedPayload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;edition&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;tokenId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;tokenId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;currencyAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;signedPayload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;signedPayload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In this block we are using the &lt;code&gt;edition.signature.generate&lt;/code&gt; function provided by thirdweb to create a custom signature for all the user's transactions. We are passing in the &lt;code&gt;tokenId&lt;/code&gt;, &lt;code&gt;quantity&lt;/code&gt;, &lt;code&gt;metadata&lt;/code&gt;, &lt;code&gt;to&lt;/code&gt;, &lt;code&gt;currencyAddress&lt;/code&gt;, and &lt;code&gt;price&lt;/code&gt; of the NFT. If it was successful we will return the &lt;code&gt;signedPayload&lt;/code&gt; to the frontend otherwise the &lt;code&gt;error&lt;/code&gt; will be returned.&lt;/p&gt;

&lt;p&gt;You also need to remove the res.send("Gm wagmi") code block 🥺.&lt;/p&gt;

&lt;p&gt;Right now you would be getting an error because we haven't yet added the token so we will create a new variable for getting the token the user is going to use to pay with:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tokenName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;nft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;find&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;tokenName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;getToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tokenName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;getToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tokenName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;getToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MATIC&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In this variable, we are getting the token from the &lt;code&gt;nft.tokens&lt;/code&gt; array. If someone passes a token that is not on the list we will use the &lt;code&gt;MATIC&lt;/code&gt; token.&lt;/p&gt;

&lt;p&gt;We also need to import nft:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;nft&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../../nft&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The final &lt;code&gt;api/generate-mint-sig.ts&lt;/code&gt; should look like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ThirdwebSDK&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@thirdweb-dev/sdk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ethers&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NextApiRequest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;NextApiResponse&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;next&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;nft&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../../nft&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;generateMintSignature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NextApiRequest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NextApiResponse&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;tokenId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tokenName&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sdk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;ThirdwebSDK&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Wallet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PRIVATE_KEY&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getDefaultProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ALCHEMY_API_URL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;edition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getEdition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0x4ebCf39BCeEA3C9790605BF292B4a2b8811C93eD&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;tokenName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;nft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;find&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;tokenName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;getToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tokenName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;getToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tokenName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;getToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MATIC&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;signedPayload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;edition&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;tokenId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;tokenId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;currencyAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;signedPayload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;signedPayload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;generateMintSignature&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Calling the api from the frontend
&lt;/h3&gt;

&lt;p&gt;Let's now use the api in our frontend! Create a new function in &lt;code&gt;index.tsx&lt;/code&gt; like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mintWithSignature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tokenId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;signedPayloadReq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/api/generate-mint-sig`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;tokenName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tokenId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;address&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;signedPayload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;signedPayloadReq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nx"&gt;signedPayload&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nft&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;edition&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;signedPayload&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;nft&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We need to use the &lt;code&gt;useEdition&lt;/code&gt; hook to access the edition contract here like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;edition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useEdition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0x4ebCf39BCeEA3C9790605BF292B4a2b8811C93eD&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We need to import this hook as well-&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useEdition&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useMetamask&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@thirdweb-dev/react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now, attach this function to the mint button-&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;mintWithSignature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Mint&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If you try to mint the NFT now it works! 🎉&lt;/p&gt;


&lt;div&gt;
  &lt;iframe src="https://loom.com/embed/7d2e59f8556847f8aa7f79e6edb100cb"&gt;
  &lt;/iframe&gt;
&lt;/div&gt;



&lt;p&gt;On the dashboard too, you would be able to see the supply increase.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--29UrFfiL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://portal.thirdweb.com/assets/portal/guides/sell-nft-multiple-currencies/nft-supply.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--29UrFfiL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://portal.thirdweb.com/assets/portal/guides/sell-nft-multiple-currencies/nft-supply.png" alt="NFT supply" width="880" height="380"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Hope you were able to sell your NFT for various tokens! If you want to have a look at the code, check out this &lt;a href="https://github.com/thirdweb-dev/examples/tree/main/typescript/nft-multiple-currencies"&gt;repo&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>web3</category>
      <category>thirdweb</category>
      <category>webdev</category>
      <category>nextjs</category>
    </item>
  </channel>
</rss>
