<?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: Paul McAviney</title>
    <description>The latest articles on Forem by Paul McAviney (@0xpaulie).</description>
    <link>https://forem.com/0xpaulie</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F664238%2Fd90933dd-e791-4b18-a10e-68fa85f3e544.jpg</url>
      <title>Forem: Paul McAviney</title>
      <link>https://forem.com/0xpaulie</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/0xpaulie"/>
    <language>en</language>
    <item>
      <title>Get Started on Celo with Infura RPC Endpoints</title>
      <dc:creator>Paul McAviney</dc:creator>
      <pubDate>Tue, 29 Nov 2022 19:03:06 +0000</pubDate>
      <link>https://forem.com/0xpaulie/get-started-on-celo-with-infura-rpc-endpoints-1po3</link>
      <guid>https://forem.com/0xpaulie/get-started-on-celo-with-infura-rpc-endpoints-1po3</guid>
      <description>&lt;p&gt;Onboarding the next wave of users to Web3 is a massive undertaking that many projects in the ecosystem are building for. One project with a unique approach to this is Celo, a layer-one blockchain network. Celo gives a superior new-user experience by being a mobile-first layer-1 blockchain that is easy to use with just a mobile phone. Your phone number acts as your address rather than a complex string, and the network allows users the option to pay gas fees with other tokens than the native currency.&lt;/p&gt;

&lt;p&gt;However, the user experience is just one side of the onboarding coin. Developer experience is the other. After all, a new network is just as good as the RPCs that let you use it. Only some developers have the resources to run a node.&lt;/p&gt;

&lt;p&gt;Infura, one of the most popular Web3 node providers, now offers Celo Network RPC nodes to all users. So if you want to start building on this mobile-first network, there’s never been a better time. Before you start building, let’s learn more about Celo.&lt;/p&gt;

&lt;p&gt;This article will provide a high-level overview of the Celo Blockchain Network and how you can start building on it using Infura. &lt;/p&gt;

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

&lt;p&gt;Celo is a &lt;a href="https://cryptonews.com/news/celo-to-be-fastest-evm-chain-by-end-of-2022-co-founder-says.htm" rel="noopener noreferrer"&gt;high-throughput layer-1 network&lt;/a&gt; that focuses on mobile users.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mapping Phone Numbers to Public Keys
&lt;/h3&gt;

&lt;p&gt;Celo is easier for mobile phone users than other networks. Celo maps phone numbers to public keys, allowing users to send tokens to people who don’t have wallets. &lt;a href="https://docs.celo.org/protocol/identity" rel="noopener noreferrer"&gt;A decentralized attestation protocol&lt;/a&gt; does the mapping and links an account to a phone number. This service never receives the phone number in clear text to &lt;a href="https://docs.celo.org/protocol/identity/odis-use-case-phone-number-privacy" rel="noopener noreferrer"&gt;maintain privacy&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Feycb8s1j6bldc4bhfxnj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Feycb8s1j6bldc4bhfxnj.png" alt="How Celo’s attestation protocol works – Image from celo.org" width="800" height="636"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As a result, user experience is better than most blockchains, as all interactions are done through phone numbers, rather than 30+ character-long strings that are easy to make mistakes with and impossible to memorize.&lt;/p&gt;

&lt;h3&gt;
  
  
  Paying Gas Fees with ERC-20 Tokens
&lt;/h3&gt;

&lt;p&gt;Another usability hurdle is that most networks require users to pay gas fees with a native token. This results in users exchanging other tokens for native ones just to be able to send transactions. &lt;/p&gt;

&lt;p&gt;This is a problem for two reasons. First, it adds a non-trivial step to every transaction if the user doesn’t have enough native tokens. Second, exchanging tokens is taxable in some countries, so they need to keep track of each time they exchange to a native token just to cover gas fees.&lt;/p&gt;

&lt;p&gt;With Celo, you can pay with any approved ERC-20 token currently available, even stablecoins, lowering yet another barrier to entry and making costs more predictable. However, there is one caveat: transactions paid with non-CELO gas currencies will cost roughly &lt;a href="https://docs.celo.org/protocol/transaction/erc20-transaction-fees#fee-currency-field" rel="noopener noreferrer"&gt;50k additional gas&lt;/a&gt;. It’s also important to note that there is a &lt;a href="https://docs.celo.org/protocol/transaction/erc20-transaction-fees#fee-currency-field" rel="noopener noreferrer"&gt;governable list of accepted currencies&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;When developing, Celo comes with a dapp SDK called &lt;a href="https://docs.celo.org/developer/contractkit/migrating-to-contractkit-v1#what-is-contractkit-version-v10" rel="noopener noreferrer"&gt;ContractKit&lt;/a&gt;. This SDK is a suite of packages that make building on Celo more straightforward. Connect, one of ContractKit’s main packages, acts as a wrapper around web3.js that handles the different currencies to pay the fees.&lt;/p&gt;

&lt;p&gt;You can set your preferred currency as default for all transactions, like in this example:&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;CeloContract&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;@celo/contractkit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;accounts&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;kit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;web3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;eth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAccounts&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nx"&gt;kit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;defaultAccount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;accounts&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;await&lt;/span&gt; &lt;span class="nx"&gt;kit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setFeeCurrency&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;CeloContract&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;StableToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this in your code, you are setting the default currency if the &lt;code&gt;feeCurrency&lt;/code&gt; field is left blank when sending a transaction. The user can still select another currency to use.&lt;/p&gt;

&lt;p&gt;ContractKit comes with a list of contract addresses that include all core Celo currencies. In the example &lt;code&gt;CeloContract.StableToken&lt;/code&gt; refers to cUSD.&lt;/p&gt;

&lt;p&gt;It’s also possible to set your preferred currency per transaction. In this example, we send cUSD and also pay with cUSD.&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="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;kit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contracts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getStableToken&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;contract&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;transfer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;recipientAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;feeCurrency&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="nx"&gt;address&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Celo’s virtual machine is also EVM compatible since it originated as a fork of &lt;a href="https://github.com/ethereum/go-ethereum" rel="noopener noreferrer"&gt;Geth&lt;/a&gt;. This compatibility enables you to reuse most of your Solidity skills when deploying your smart contracts on Celo. However, there are some notable differences.&lt;/p&gt;

&lt;p&gt;The first difference is that transaction objects have additional fields like &lt;code&gt;feeCurrency&lt;/code&gt;, &lt;code&gt;gatewayFee&lt;/code&gt;, and &lt;code&gt;gatewayFeeRecipient&lt;/code&gt;. They provide full-node incentives and allow users to pay their gas fees with different tokens. This doesn’t affect you when porting smart contracts from Ethereum to Celo, but it could be an issue when porting from Celo to Ethereum.&lt;/p&gt;

&lt;p&gt;The second difference could have implications for your Ethereum-based smart contracts. The &lt;code&gt;DIFFICULTY&lt;/code&gt; and &lt;code&gt;GASLIMIT&lt;/code&gt; opcodes aren’t supported, and the fields are also missing from block headers.&lt;/p&gt;

&lt;p&gt;A third difference is that the key derivation path is &lt;code&gt;m/44'/52752'/0'/0&lt;/code&gt; and not &lt;code&gt;m/44'/60'/0'/0&lt;/code&gt; like in Ethereum. Essentially, this derivation path allows wallets to generate different keys from one seed phrase.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Network is Carbon Negative
&lt;/h3&gt;

&lt;p&gt;CO2 production by blockchain networks has been a huge talking point in the last few years. Coming from Bitcoin, many of the early networks used the Proof-of-Work consensus algorithm to eliminate Sybil attacks.&lt;/p&gt;

&lt;p&gt;The Celo protocol uses &lt;a href="https://docs.celo.org/protocol/pos" rel="noopener noreferrer"&gt;BFT Proof-of-Stake&lt;/a&gt;, which minimizes energy usage of the network by over 90%. Plus, it can create a new block in five seconds, less than half the time Ethereum needs.&lt;/p&gt;

&lt;p&gt;Furthermore, all blocks are finalized immediately, so you and your users don’t have to wait for their actions to be written on-chain.&lt;/p&gt;

&lt;p&gt;All this optimization still produces CO2, so &lt;a href="https://www.wren.co/profile/celo" rel="noopener noreferrer"&gt;Celo uses projects like Wren&lt;/a&gt;, a carbon offset subscription service that offsets 65.7 tons of CO2 monthly to get carbon negative. With tech-funded rainforest protection, Celo has already saved over 30,000 tons of CO2. &lt;/p&gt;

&lt;h2&gt;
  
  
  Why Use Celo with Infura?
&lt;/h2&gt;

&lt;p&gt;Infura offers free RPCs for prominent wallets, and &lt;a href="https://www.infura.io/customers" rel="noopener noreferrer"&gt;many big Web3 projects&lt;/a&gt; use them as their RPC provider, including Brave, Uniswap, Compound, Gnosis, and Maker, just to name a few. Additionally, Infura has achieved 99.99% uptime and about 10 times faster response times than other service providers like Alchemy or Quicknode.&lt;/p&gt;

&lt;p&gt;ConsenSys, the company behind Infura also created and maintains crucial Web3 projects such as &lt;a href="https://metamask.io/" rel="noopener noreferrer"&gt;MetaMask&lt;/a&gt; and the &lt;a href="https://trufflesuite.com/docs/" rel="noopener noreferrer"&gt;Truffle Suite&lt;/a&gt;. So the shared know-how of creating wallets, dev tools, and RPCs creates synergies you won’t get from any other RPC provider. This also means you get trusted and complementary end-to-end tooling from the ConsenSys suite of products that flawlessly integrate with Infura RPCs.&lt;/p&gt;

&lt;p&gt;With the release of &lt;a href="https://blog.infura.io/post/celo-x-infura-continuing-our-multi-chain-expansion-with-social-regenerative-defi" rel="noopener noreferrer"&gt;Celo RPCs&lt;/a&gt;, Infura now supports &lt;a href="https://www.infura.io/networks" rel="noopener noreferrer"&gt;10 different networks&lt;/a&gt;, so you can build on multiple chains at once. Best of all, it’s free to access these networks and their archived data!&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Celo is an exciting chain that tackles Web3 user and developer experience pain-points with innovative solutions. With its mobile-first approach, users can interact with the network and receive tokens with their phone number rather than a crypto wallet, making onboarding to the network easier for Web3 newcomers.&lt;/p&gt;

&lt;p&gt;With the option to pay gas fees with other tokens rather than the native currency, Celo also removed a massive hurdle in the daily use of a blockchain network. Other networks require fees paid with a native and potentially volatile token.&lt;/p&gt;

&lt;p&gt;Now that Infura offers RPC nodes for the Celo network, it’s the perfect time to start building on this mobile-first blockchain network. For more information, &lt;a href="https://docs.infura.io/infura/networks/celo" rel="noopener noreferrer"&gt;check out Infura’s docs&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>watercooler</category>
    </item>
    <item>
      <title>How to Run Ganache in a Browser</title>
      <dc:creator>Paul McAviney</dc:creator>
      <pubDate>Mon, 31 Oct 2022 17:49:43 +0000</pubDate>
      <link>https://forem.com/0xpaulie/how-to-run-ganache-in-a-browser-4ndg</link>
      <guid>https://forem.com/0xpaulie/how-to-run-ganache-in-a-browser-4ndg</guid>
      <description>&lt;p&gt;When developing Web3 projects, it helps to have a local blockchain devnet for testing. &lt;a href="https://trufflesuite.com/ganache/"&gt;Ganache&lt;/a&gt; is one of the most popular tools for this in the Ethereum ecosystem, and part of &lt;a href="https://www.google.com/url?q=https://trufflesuite.com/&amp;amp;sa=D&amp;amp;source=docs&amp;amp;ust=1666974697266273&amp;amp;usg=AOvVaw2MJDRYhKuW4DmJ8Qv97XKz"&gt;Truffle&lt;/a&gt;. Ganache allows you to set up a local blockchain with different settings to thoroughly test your smart contracts before deployment.&lt;/p&gt;

&lt;p&gt;Seeing a local blockchain’s output in the terminal helps you to understand how your project will behave in a live environment. The ability to set the output to variables to manipulate some frontend code is even more useful. Some users may not know that you can do this by running Ganache in your browser.&lt;/p&gt;

&lt;p&gt;This article explores how to run Ganache in your browser and highlights three great new features that make developing your Web3 projects easier.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ganache in the Browser
&lt;/h3&gt;

&lt;p&gt;Running a local blockchain instance to test your smart contracts is an essential step in the Web3 development process. By testing in this manner, you confirm things are working correctly before using a node service, such as &lt;a href="https://infura.io/"&gt;Infura&lt;/a&gt;, to deploy your contracts to a testnet or mainnet. This minimizes the risk of ramping up daily limits and ensures you only need to deploy once. Ganache is an excellent tool that simulates the Ethereum network and allows developers to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://trufflesuite.com/blog/introducing-ganache-7/#2-fork-any-ethereum-test-network-without-waiting-for-sync-time"&gt;Fork any Ethereum network without waiting to sync&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://trufflesuite.com/blog/introducing-ganache-7/#5-mine-blocks-instantly-at-interval-or-on-demand"&gt;Establish block mining rules (instant, on-demand, intervals)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://trufflesuite.com/blog/introducing-ganache-7/#7-impersonate-any-account"&gt;Impersonate any real account without needing their private keys&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Make function calls with Ethereum JSON-RPC support&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, many who use this tool may be unaware that, since v7.0.0.0, Ganache can also run in your browser. Running in the browser allows you to set the local blockchain’s output to variables, which you can then use to test your frontend code. This visual process helps you to understand how your users will interact with your project and also enables you to test your dapp entirely offline (when using a local instance).&lt;/p&gt;

&lt;p&gt;By first running Ganache in the browser and fine-tuning how your dapp reacts, you can easily switch the provider to your node service API once things are working as intended. Additionally, since Ganache’s latest update (v7.3.2 at the time of writing), you can now&lt;a href="https://trufflesuite.com/blog/three-new-ganache-features-to-improve-your-developer-experience/#zero-config-mainnet-forking-now-available-in-the-browser"&gt; fork the Ethereum mainnet when running Ganache in the browser&lt;/a&gt;. This allows you to interact with real accounts and contracts through your frontend code.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Project
&lt;/h3&gt;

&lt;p&gt;In this section, we will create a basic smart contract using Truffle and its VS Code extension. Then, we’ll first deploy our contract to Ganache via the command line. Afterward, we will create a simple frontend to use Ganache in the browser and interact with our deployed contract.&lt;/p&gt;

&lt;h4&gt;
  
  
  Requirements
&lt;/h4&gt;

&lt;p&gt;For this project, we will use the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://nodejs.org/en/"&gt;NodeJS / NPM&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://trufflesuite.com/docs/truffle/getting-started/installation/"&gt;Truffle&lt;/a&gt; &amp;amp; &lt;a href="https://github.com/trufflesuite/ganache#readme"&gt;Ganache&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://code.visualstudio.com/Download"&gt;The VS Code Editor&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=trufflesuite-csi.truffle-vscode"&gt;Truffle for VS Code Extension&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Step 1 – Installation
&lt;/h4&gt;

&lt;p&gt;First, we can run the command &lt;code&gt;node --version&lt;/code&gt; in our terminal to ensure NodeJS and NPM are &lt;a href="https://nodejs.org/en/"&gt;properly installed&lt;/a&gt; on our machine.&lt;/p&gt;

&lt;p&gt;Next, we will install Truffle and Ganache by running 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;npm install -g truffle ganache
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Checking the version number for Truffle and Ganache with &lt;code&gt;truffle --version&lt;/code&gt; and &lt;code&gt;ganache --version&lt;/code&gt; respectively will tell us if both tools were installed successfully. &lt;/p&gt;

&lt;p&gt;The next step is to &lt;a href="https://code.visualstudio.com/Download"&gt;install VS Code&lt;/a&gt;, then navigate to the &lt;strong&gt;Extensions&lt;/strong&gt; tab in the editor and search for &lt;strong&gt;Truffle for VS Code&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BxpnMZcp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rmke8bhz3y1b6wmre3a4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BxpnMZcp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rmke8bhz3y1b6wmre3a4.png" alt="" width="402" height="121"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--481k5xn---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kl70ae6tlclbrqjxbpoo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--481k5xn---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kl70ae6tlclbrqjxbpoo.png" alt="" width="859" height="269"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With everything now installed, we are ready to start working on the project.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 2 – Set Up the Project
&lt;/h4&gt;

&lt;p&gt;With the Truffle for VS Code extension, we can easily create a new Truffle project through the VS Code command palette. Press &lt;code&gt;ctrl + shift + P&lt;/code&gt; in the editor to open up the command palette and type &lt;code&gt;truffle&lt;/code&gt; to see a list of commands we can use. Select &lt;strong&gt;Truffle: New Solidity Project&lt;/strong&gt; and then &lt;strong&gt;create basic&lt;/strong&gt; project to create a new project in the desired folder.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OEGlS7HQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rmaavbpygcfhgy5coku1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OEGlS7HQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rmaavbpygcfhgy5coku1.png" alt="" width="602" height="191"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This creates an initialized project with a simple folder structure and example code we can use if we wish. &lt;/p&gt;

&lt;p&gt;The ability to use &lt;code&gt;console.log&lt;/code&gt; in our smart contract code is another great new feature &lt;a href="https://trufflesuite.com/blog/three-new-ganache-features-to-improve-your-developer-experience/#ability-to-use-consolelog-from-solidity"&gt;recently available for Ganache&lt;/a&gt;. Before we create the smart contract for our project, let’s set that up by installing the required package. Navigate to the project folder in the terminal and type 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;npm install @ganache/console.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 3 – Write the Smart Contract
&lt;/h4&gt;

&lt;p&gt;The smart contract for our project will be a basic one we can donate some ETH to and request to see the balance. &lt;/p&gt;

&lt;p&gt;In the &lt;strong&gt;contracts&lt;/strong&gt; folder, create a new file and call it &lt;strong&gt;SimpleContract.sol&lt;/strong&gt;. Next, fill it with the following smart contract code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight solidity"&gt;&lt;code&gt;&lt;span class="c1"&gt;// SPDX-License-Identifier: UNLICENSED
&lt;/span&gt;&lt;span class="k"&gt;pragma&lt;/span&gt; &lt;span class="n"&gt;solidity&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="mf"&gt;0.8&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'@ganache/console.log/console.sol'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;contract&lt;/span&gt; &lt;span class="n"&gt;SimpleContract&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="k"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s"&gt;#################################################&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;
    &lt;span class="s"&gt;'####         Now Deploying Contract          ####&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;
    &lt;span class="s"&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;function&lt;/span&gt; &lt;span class="n"&gt;donate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;payable&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Successfully Donated '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;getBalance&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;view&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint256&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"This contract's balance is:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;this&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nb"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kt"&gt;address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;this&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nb"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Needed in order to receive payments
&lt;/span&gt;  &lt;span class="k"&gt;receive&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;external&lt;/span&gt; &lt;span class="k"&gt;payable&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;The code in our smart contract is relatively simple. It displays a message in the console when we deploy our smart contract, provides the functionality to donate ETH and query the balance, and prints messages in the console when calling the functions.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 4 – Deploy to Ganache
&lt;/h4&gt;

&lt;p&gt;After installing the Truffle for VS Code Extension, we can easily deploy by right-clicking the smart contract file and choosing &lt;strong&gt;Deploy Contracts.&lt;/strong&gt; However, if we want to see our console messages, we will have to use our own terminal rather than the one built into VS Code. This could potentially change in the future, but for now, we will have to create a simple migration script to carry out the deployment.&lt;/p&gt;

&lt;p&gt;In the &lt;strong&gt;migrations&lt;/strong&gt; folder, create a new script called &lt;code&gt;1_SimpleContract.js&lt;/code&gt; and input the following code:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;SimpleContract&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;artifacts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SimpleContract&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;deployer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;deployer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;deploy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;SimpleContract&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;Next, open up a new terminal window and start Ganache:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;This terminal window is where we will see our console messages when they appear. We now have two terminal windows open: one running Ganache and the other open in the folder of our Truffle project.&lt;/p&gt;

&lt;p&gt;In the terminal window that’s open in our Truffle project’s location, type the following command to initiate the deployment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;truffle migrate --network development 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the deployment is successful, we can see our console message printed in the terminal:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uOiX6eMQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/16is2vjp508aw5a0rhp8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uOiX6eMQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/16is2vjp508aw5a0rhp8.png" alt="" width="672" height="269"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Great! Our contract is live on our local Ganache instance! We’ll leave Ganache running for now so we can interact with our contract using the browser. Before we get to that, copy the &lt;code&gt;contract address&lt;/code&gt; from the output in the terminal where we typed the &lt;code&gt;migrate&lt;/code&gt; command. We will use this address to point our frontend to our smart contract.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HbM1DeRh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ktlxsv38patytq7hj7sg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HbM1DeRh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ktlxsv38patytq7hj7sg.png" alt="" width="685" height="334"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 5 – Build the Frontend
&lt;/h4&gt;

&lt;h5&gt;
  
  
  5.a – Setup
&lt;/h5&gt;

&lt;p&gt;For the frontend of this project, we will use React. Navigate to a new empty folder and type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx create-react-app ganache-browser-test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we will install Web3.JS to easily interact with our smart contract. Navigate into our new project folder and install Web3.JS with 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;cd ganache-browser-test
npm install web3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Newer versions of create-react-app don’t play nicely with Web3.JS, so we need to install a specific version of React Scripts. We can do so with 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;npm install --save-exact react-scripts@4.0.3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, to use Ganache in our browser, we will install it directly as a dependency:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install ganache
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alternatively, you can add the CDN link in the html to access Ganache from the browser:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/npm/ganache@7.3.2/dist/web/ganache.min.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before we start working on the frontend code, we need to create a file containing our contract’s ABI so that we can interact with our smart contract. We can copy that file directly from our Truffle project. Navigate to the &lt;strong&gt;build/contracts&lt;/strong&gt; folder in our Truffle project and copy the &lt;strong&gt;SimpleContract.json&lt;/strong&gt; file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ESaTgLSY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tnyf5goks4u9tmkoqg4y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ESaTgLSY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tnyf5goks4u9tmkoqg4y.png" alt="" width="249" height="477"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, open up our frontend project in the editor and create a new folder called &lt;strong&gt;abi&lt;/strong&gt;. In that folder, paste the &lt;strong&gt;SimpleContract.json&lt;/strong&gt; file. The file structure for our frontend now looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TwRBgj8M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w0xail05l47xu32bsjiz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TwRBgj8M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w0xail05l47xu32bsjiz.png" alt="" width="246" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  5.b – The Frontend Code
&lt;/h5&gt;

&lt;p&gt;With all the setup out of the way, we can start working on our frontend. First, open the &lt;strong&gt;App.js&lt;/strong&gt; file in the &lt;strong&gt;src&lt;/strong&gt; folder and replace the boilerplate code with this:&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;useState&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;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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./App.css&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;SimpleContract&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;./abi/SimpleContract.json&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;ganache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ganache&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;Web3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;web3&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;options&lt;/span&gt; &lt;span class="o"&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;provider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ganache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&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;web3&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;Web3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://127.0.0.1:8545&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_ADDRESS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;YOUR_CONTRACT_ADDRESS&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;  
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;USER_ADDRESS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;web3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;utils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toChecksumAddress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;YOUR_ACCOUNT_ADDRESS&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;contractInstance&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;web3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;eth&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="nx"&gt;SimpleContract&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;abi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;CONTRACT_ADDRESS&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;App&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;contractBalance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setContractBalance&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="mi"&gt;0&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;donate&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="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;donationAmount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#donationAmount&lt;/span&gt;&lt;span class="dl"&gt;'&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&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;contractInstance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;donate&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;USER_ADDRESS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;web3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;utils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toWei&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;donationAmount&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;donate response:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&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;getBalance&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="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;response&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;contractInstance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getBalance&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;call&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;getBalance response:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;setContractBalance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;web3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;utils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fromWei&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;App&lt;/span&gt;&lt;span class="dl"&gt;"&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;header&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;App-header&lt;/span&gt;&lt;span class="dl"&gt;"&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;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Ganache&lt;/span&gt; &lt;span class="nx"&gt;In&lt;/span&gt; &lt;span class="nx"&gt;The&lt;/span&gt; &lt;span class="nx"&gt;Browser&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&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="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;input&lt;/span&gt;
            &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;number&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
            &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;donationAmount&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
            &lt;span class="nx"&gt;defaultValue&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mf"&gt;0.01&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="sr"&gt;/&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="nx"&gt;label&lt;/span&gt; &lt;span class="nx"&gt;htmlFor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;donationAmount&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;ETH&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/label&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="nx"&gt;br&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/br&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="nx"&gt;button&lt;/span&gt;
            &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;donate&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
            &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;'&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="nx"&gt;donate&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;Donate&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;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="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;button&lt;/span&gt;
            &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;getBalance&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
            &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;'&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="nx"&gt;getBalance&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;Get&lt;/span&gt; &lt;span class="nx"&gt;Contract&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="sr"&gt;/button&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="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;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;contractBalance&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;ETH&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/header&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;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;App&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Be sure to change &lt;code&gt;CONTRACT_ADDRESS&lt;/code&gt; to the address we received when deploying our smart contract back in Step 4. As well, the &lt;code&gt;USER_ADDRESS&lt;/code&gt; is the account that will call the functions. We can get this from the list of accounts that displays when we first started our Ganache instance in the terminal:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---nMt2mKv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k272mv0ud9k27anqmz44.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---nMt2mKv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k272mv0ud9k27anqmz44.png" alt="" width="494" height="268"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Any of these account addresses will work.&lt;/p&gt;

&lt;p&gt;Before we move on, let’s take a second to walk through the code we wrote:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We import our dependencies and &lt;code&gt;SimpleContract&lt;/code&gt; JSON file.&lt;/li&gt;
&lt;li&gt;Set the &lt;code&gt;ganache&lt;/code&gt;and &lt;code&gt;Web3&lt;/code&gt; variables.&lt;/li&gt;
&lt;li&gt;Create an empty &lt;code&gt;options&lt;/code&gt; variable that we initialize our &lt;code&gt;provider&lt;/code&gt; instance with.

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Note&lt;/strong&gt;: This &lt;code&gt;options&lt;/code&gt; variable is where we would set &lt;a href="https://github.com/trufflesuite/ganache#documentation"&gt;any of the options&lt;/a&gt; we would like our local blockchain instance to include, such as forking Mainnet or Goerli, when running Ganache strictly in the browser (without it running in our other terminal window).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Initialize our &lt;code&gt;web3&lt;/code&gt; object using our &lt;code&gt;localhost URL&lt;/code&gt; and port &lt;code&gt;8545&lt;/code&gt;, where our Ganache instance is already running.

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Note&lt;/strong&gt;: You can run Ganache strictly in the browser at this point by using the &lt;code&gt;provider&lt;/code&gt; variable instead of localhost. We are using &lt;code&gt;localhost&lt;/code&gt; in this case since we want to interact with our already deployed smart contract and see our &lt;code&gt;console.log&lt;/code&gt; messages in the terminal output.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Set our &lt;code&gt;CONTRACT_ADDRESS&lt;/code&gt; and &lt;code&gt;USER_ADDRESS&lt;/code&gt; variables.&lt;/li&gt;
&lt;li&gt;Create a contract instance we can use to call our functions in the &lt;code&gt;App&lt;/code&gt; code.&lt;/li&gt;
&lt;li&gt;Create the &lt;code&gt;contractBalance&lt;/code&gt; React state variable and its &lt;code&gt;set&lt;/code&gt; method.&lt;/li&gt;
&lt;li&gt;Define our &lt;code&gt;donate&lt;/code&gt; and &lt;code&gt;getBalance&lt;/code&gt; functions.&lt;/li&gt;
&lt;li&gt;Finally, we return the &lt;code&gt;html&lt;/code&gt; for our frontend.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  5.c – Run the Project
&lt;/h5&gt;

&lt;p&gt;Now we can run our app with &lt;code&gt;npm start&lt;/code&gt; to display our frontend, which looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--t3Czlh9e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ohc6s8o4ku1s4zbqzidy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--t3Czlh9e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ohc6s8o4ku1s4zbqzidy.png" alt="" width="760" height="414"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When we test our project, we can see the results and our &lt;code&gt;console.log&lt;/code&gt; messages displayed on the terminal window which is running Ganache, and the ETH balance on our frontend successfully updates with the new balance.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4lVMR1KK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/milqcjnq4vi7unowjxas.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4lVMR1KK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/milqcjnq4vi7unowjxas.png" alt="" width="669" height="119"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KcBTCYxp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7pnstzj5m45ltpldduwm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KcBTCYxp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7pnstzj5m45ltpldduwm.png" alt="" width="387" height="33"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 6 – Fork Goerli or Mainnet with Ganache in the Browser
&lt;/h4&gt;

&lt;p&gt;Now that we know our project functions properly on a locally running instance of Ganache, the next step is to run it on a forked version of a testnet and then mainnet. We won’t run through the actual process of doing that in this article, but setting it up to do so is simple. All we need to do is change a few lines of our frontend code.&lt;/p&gt;

&lt;p&gt;First, the options variable needs to specify which network we wish to fork:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;fork&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;network&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;goerli&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;Or:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;fork&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;network&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mainnet&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;Then we need to update our &lt;code&gt;web3&lt;/code&gt; variable declaration:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;web3&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;Web3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we need to make sure that we update &lt;code&gt;CONTRACT_ADDRESS&lt;/code&gt; with our address on whichever network we are forking. We also need to update &lt;code&gt;USER_ADDRESS&lt;/code&gt; to an account address on the same network that has sufficient funds to donate to our contract.&lt;/p&gt;

&lt;p&gt;When forking mainnet, that section of code could look something like this:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;fork&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;network&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mainnet&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;provider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ganache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&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;web3&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;Web3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;provider&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_ADDRESS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0x692586eaC70114C8F4714D89E7f72FAAbaeE0Cd7&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;  
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;USER_ADDRESS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;web3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;utils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toChecksumAddress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0xCe7A99Bba7018fa455E6eD5CF88a7F26010F1E8F&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;And with that, we could test our project with a forked version of mainnet using Ganache in our browser.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Testing projects by creating an interface helps to visualize how your dapp is running and gives you a better idea of how it will perform for users once on mainnet. Running in your browser while testing your frontend code is one of the features that make Ganache such a powerful tool in your development toolkit. For more information about working with Ganache or to contribute to the project, &lt;a href="https://github.com/trufflesuite/ganache#documentation"&gt;check out their Github&lt;/a&gt; or &lt;a href="https://trufflesuite.com/docs/ganache/quickstart/"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>web3</category>
      <category>blockchain</category>
      <category>truffle</category>
      <category>ganache</category>
    </item>
    <item>
      <title>Infura’s Plans To Launch A New Decentralized Infrastructure Protocol And Why It Matters</title>
      <dc:creator>Paul McAviney</dc:creator>
      <pubDate>Wed, 21 Sep 2022 14:37:21 +0000</pubDate>
      <link>https://forem.com/0xpaulie/infuras-plans-to-launch-a-new-decentralized-infrastructure-protocol-and-why-it-matters-2inl</link>
      <guid>https://forem.com/0xpaulie/infuras-plans-to-launch-a-new-decentralized-infrastructure-protocol-and-why-it-matters-2inl</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;At &lt;a href="https://ethberlin.ooo/"&gt;ETH Berlin&lt;/a&gt; recently, &lt;a href="https://twitter.com/infura_io/status/1570794318067290112?s=20&amp;amp;t=k28Iqc0qT3Y6nNcL4lipWw"&gt;Infura announced plans for a new decentralized infrastructure network&lt;/a&gt;. This decentralized network has the potential to vastly improve how web3 developers and end-users access and interact with the data on blockchains.&lt;/p&gt;

&lt;p&gt;Why is this a big deal? And what could it mean for Web3? Let’s take a look.&lt;/p&gt;

&lt;h3&gt;
  
  
  Decentralized Protocols
&lt;/h3&gt;

&lt;p&gt;One of the most important innovations Web3 and blockchain technology make possible are &lt;strong&gt;decentralized protocols&lt;/strong&gt;—networks and communities where anyone and everyone can participate. Protocols are a powerful new form of human coordination using technology and protocols like Bitcoin and Ethereum have led the way for so many others to emerge: NEAR, Polygon, and Arbitrum, just to name a few. &lt;/p&gt;

&lt;p&gt;But what about the &lt;strong&gt;infrastructure and protocols&lt;/strong&gt; that exist on top of these networks? Many companies creating the building blocks are operating in Web2 terms with centralized ownership and access to their services. As Web3 technology grows and matures, the need for &lt;strong&gt;decentralized protocols and infrastructure&lt;/strong&gt; grows with it. That’s why Infura is launching a new infrastructure protocol for node services.&lt;/p&gt;

&lt;p&gt;Node services are how some dapps access blockchain data in Web3. While some larger organizations choose to host their own nodes, self-hosting can be complicated and expensive. As a result, many developers rely on companies like Infura to manage the infrastructure and blockchain access for them.&lt;/p&gt;

&lt;p&gt;A decentralized infrastructure protocol—one that offers this access but isn’t controlled by a single centralized entity—is a critical piece to completing the Web3 tech stack. &lt;/p&gt;

&lt;h2&gt;
  
  
  What is a Decentralized Infrastructure Protocol?
&lt;/h2&gt;

&lt;p&gt;Let’s break down this question of centralized versus decentralized a bit further.&lt;/p&gt;

&lt;p&gt;In a &lt;em&gt;centralized&lt;/em&gt; node service, a single entity controls the protocol and infrastructure. Similar to how Web2 companies like Twitter or Facebook: one entity hosts the server that ensures the service is operational, gatekeeping the user data and pocketing the revenue. As a result, end-users like you and me only have one entry point into the service, and zero control over what happens behind the scenes. &lt;/p&gt;

&lt;p&gt;In the case of a node provider, a single entity is responsible for keeping the service operational, the infrastructure running, and the node responses flowing. While there are multiple nodes running, they are all controlled by this single entity. If the centralized entity or its infrastructure goes down, so does the entire service, along with any applications that rely on that service. &lt;a href="https://en.wikipedia.org/wiki/2021_Facebook_outage"&gt;Remember when Facebook went offline on October 4th in 2021&lt;/a&gt;? That’s a prime example. Millions of people and services were disconnected as a result of their server outage. This is the principal shortcoming of centralized infrastructure: it can never guarantee 100% uptime the way a decentralized network can. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--q48KLCNZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ea26kwrtz7jtv14prjtp.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--q48KLCNZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ea26kwrtz7jtv14prjtp.jpg" alt="A centralized node provider with a single entry point leading into multiple nodes, which in turn, lead into the blockchain" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In a &lt;em&gt;decentralized&lt;/em&gt; node service, there are multiple entities all joining together to support the protocol, host the nodes, validate the data, and distribute the risk of infrastructure. The decentralization of responsibilities is closer to the ultimate goals of Web3 and a truly permissionless infrastructure. &lt;/p&gt;

&lt;p&gt;And, because there are multiple providers, users will have the choice of which provider to use. If a provider goes down, or one makes technical decisions the user doesn’t like, then the user can easily switch to a new provider. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--r3DqOqxS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vhq1q0d2azmptsefs5v8.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--r3DqOqxS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vhq1q0d2azmptsefs5v8.jpg" alt="A decentralized node providing service with many providers and multiple points of entry" width="800" height="664"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With this many actors, there’s a requirement for ways to agree on upgrades, revenue sharing, architectural changes, and so on. We can already see this on Ethereum with the EIP system. From past experience, this often means implementing decentralized governance like a DAO.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why is Decentralized Infrastructure Important?
&lt;/h2&gt;

&lt;p&gt;So why is this decentralized node protocol a big deal? &lt;/p&gt;

&lt;p&gt;As I mentioned earlier, decentralized &lt;em&gt;networks&lt;/em&gt; have progressed significantly as well as some of the protocols, DeFi above all. However, decentralized data &lt;strong&gt;access&lt;/strong&gt; is one of the most important components of the Web3 tech stack. &lt;/p&gt;

&lt;p&gt;Until now, node access has been mostly centralized, since the vast majority of users access the blockchain through the node providing services. Without a decentralized node access protocol and infrastructure, we don’t really have decentralized Web3, which is the ultimate goal of this industry and ecosystem. A decentralized infrastructure protocol gives us: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;High-throughput and reliability&lt;/strong&gt; - a proven architectural solution spread out over multiple entities reduces the risk of downtime and failures. It can ensure that users can access the data they need.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Increased transparency&lt;/strong&gt; - decentralized solutions, like open source software, often result in a higher level of transparency.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Improved cooperation&lt;/strong&gt; - Instead of competing, protocol providers collaborate to create a more effective and reliable infrastructure protocol.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;How this will evolve is yet to be seen, but Infura plans to release the new protocol in stages. &lt;/p&gt;

&lt;h2&gt;
  
  
  What Can You Do?
&lt;/h2&gt;

&lt;p&gt;Since Infura’s announcement at ETH Berlin was high-level, we don’t know yet how this decentralized infrastructure protocol will be implemented. &lt;/p&gt;

&lt;p&gt;That said, there was an open call for infrastructure providers to get involved. Qualified providers can &lt;a href="https://infura.io/resources/network/decentralized-infrastructure-network-early-access-program?utm_source=twitter&amp;amp;utm_medium=organicsocial&amp;amp;utm_campaign=2022_Sep_decentralized-network-eap-infura_announcement_content"&gt;sign up for the early access program&lt;/a&gt; to help construct the test network. In the announcement, they listed the following qualifications:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Experience running blockchain infrastructure&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Willingness to actively participate and provide feedback&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Interest in decentralizing blockchain API access&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to learn more about this decentralized network, keep an eye on &lt;a href="https://blog.infura.io/"&gt;Infura’s official channels&lt;/a&gt; for more information.&lt;/p&gt;

</description>
      <category>web3</category>
      <category>blockchain</category>
      <category>decentralization</category>
      <category>infura</category>
    </item>
    <item>
      <title>How Does Polygon Help Ethereum Scale?</title>
      <dc:creator>Paul McAviney</dc:creator>
      <pubDate>Mon, 12 Sep 2022 20:20:04 +0000</pubDate>
      <link>https://forem.com/0xpaulie/how-does-polygon-help-ethereum-scale-59cc</link>
      <guid>https://forem.com/0xpaulie/how-does-polygon-help-ethereum-scale-59cc</guid>
      <description>&lt;h3&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Since its inception in 2014, Ethereum has established itself as the de facto leader of blockchain platforms capable of supporting turing-complete smart contracts.&lt;/p&gt;

&lt;p&gt;Ethereum has been instrumental in bringing about a revolution that we now know as web3. The largest decentralized exchange, NFT marketplace, and yield farming protocol all reside on Ethereum. The chain is responsible for handling billions of dollars worth of value, and it has opened up avenues for creators and investors that were previously unfathomable.&lt;/p&gt;

&lt;p&gt;Although Ethereum dapps have enjoyed an immense amount of popularity amongst their users, they are nowhere close to achieving mass adoption. The sum of people who have used dapps still number only in the few millions. One of the biggest reasons for this is the scaling handicaps endemic to the chain. It becomes unusable very quickly for everyone barring a few high net-worth users.&lt;/p&gt;

&lt;p&gt;Fortunately, there have been serious efforts made by the community to help Ethereum scale. By far, the most popular scaling solution available in the market today is the Polygon POS (Proof of Stake) sidechain. In this article, we are going to explore what Polygon is and how it overcomes Ethereum’s drawbacks. Finally, we will make a side-by-side comparison of both chains’ performances by creating an NFT-minting smart contract.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;The Problem with Ethereum&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Ethereum, despite its market leader position, suffers from a host of problems:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Low Transaction Throughput&lt;/strong&gt;: Ethereum can handle only 15 transactions per second. Compared to solutions like Visa or Mastercard, which handle over 25,000 transactions per second, this figure is scant.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High Gas Fees&lt;/strong&gt;: When a chain can handle few transactions, it must increase processing costs when the transaction volumes are high. Ethereum is notorious for its high gas fees. For instance, not long ago, it reached almost 7000 Gwei during a popular NFT mint (called Otherside). During this period, it would’ve cost you in excess of $500 to perform even the most basic transaction.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Slow Transaction Finality&lt;/strong&gt;: Ethereum adds a block to its chain approximately once every 15 seconds. Since there are multiple miners competing to mine blocks at the same time, a block cannot be considered final until at least 4-5 blocks have been added on top of it. In essence, it takes more than a minute for a transaction to be considered final. With applications like games and financial tools, such a slow transaction finality is simply not acceptable.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;The Solution&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In order to achieve mass adoption and acceptance, it is imperative that a solution be developed on top of Ethereum that addresses its most glaring problems. In essence, we need a solution that has the following features:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Low-cost&lt;/strong&gt;: Even the most computationally intensive transactions shouldn’t cost more than a few cents.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fast&lt;/strong&gt;: Transactions are confirmed almost instantly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;EVM Compatible&lt;/strong&gt;: Developers don’t need to learn new tooling or languages in order to build on the solution.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interoperable with Ethereum&lt;/strong&gt;: Easy to deposit and withdraw funds to and from Ethereum and the solution.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Engaged community&lt;/strong&gt;: A community that is committed to improving the solution over time as well as building user-friendly dapps on top of it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sustainable:&lt;/strong&gt; Any solution looking to reach mass adoption must also be environmentally conscious.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Ethereum core developers are working on Layer 1 scaling fixes, such as &lt;a href="https://ethereum.org/en/upgrades/sharding/"&gt;sharding&lt;/a&gt;, but these solutions are nowhere near completion. We need solutions available today that are easy for anyone to get started on.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Introducing Polygon&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The creators of Polygon designed a chain with all the aforementioned features in mind. Since its inception in 2017, the Polygon chain has gone on to become one of the most popular Ethereum scaling solutions.&lt;/p&gt;

&lt;p&gt;Technically speaking, Polygon is an Ethereum sidechain. A sidechain is an independent blockchain that is connected to Ethereum via a bridge. Unlike L2s, sidechains do not inherit the security features of the main Ethereum chain. Instead, they implement their own consensus protocols and block parameters. As a result, sidechains aren’t required to post state changes and transaction data to Ethereum (whereas L2s are).&lt;/p&gt;

&lt;p&gt;The greater independence of sidechains from Ethereum makes Polygon slightly more centralized but also enables it to achieve extraordinarily high levels of throughput.&lt;/p&gt;

&lt;p&gt;The following are the improvements that Polygon has been able to achieve over Ethereum:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;High transaction speeds&lt;/strong&gt;: Polygon is capable of handling up to 65,000 tx/second, comparable to the scale of its centralized rivals.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Low transaction costs&lt;/strong&gt;: Even the heaviest transactions on Polygon cost only a few cents. In most cases, a 10,000x reduction in cost can be observed vis-à-vis Ethereum.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Instant transaction finality&lt;/strong&gt;: Polygon’s consensus protocol guarantees that transactions are confirmed almost instantly (less than 2 seconds).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;EVM compatible&lt;/strong&gt;: Polygon is built on the same software as Ethereum. Therefore, Ethereum developers can build on Polygon using the exact same tools.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Strong community&lt;/strong&gt;: The Polygon team has spent millions of dollars to build a robust community of builders, investors, and users. It is already home to some of the most popular dapps on Ethereum with better UX and much cheaper costs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Low energy consumption&lt;/strong&gt;: Polygon uses the Proof-of-Stake protocol, which consumes 99.9% less energy than its PoW counterpart. In fact, Polygon has committed to being &lt;a href="https://polygon.technology/sustainability/"&gt;carbon negative&lt;/a&gt; by the end of 2022, making it one of the largest environment-friendly blockchains in the market today.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;A Note on Polygon PoS Security&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Unlike other sidechains, Polygon PoS does have a method in which it is able to inherit the security of Ethereum. The Polygon PoS chain utilizes the &lt;a href="https://docs.polygon.technology/docs/develop/ethereum-polygon/plasma/getting-started/"&gt;Plasma Bridge&lt;/a&gt; in order to maintain and guarantee a high level of security. Plasma has a unique exit mechanism, basically a set of smart contracts to help move assets and checkpoints for verification, which enables Polygon PoS to leverage Ethereum’s security. &lt;/p&gt;

&lt;p&gt;The only drawback here is withdrawals from Polygon to Ethereum through the Plasma Bridge must go through a 7-day withdrawal period. Quicker withdrawals (within 30 minutes to 3 hours) are possible with the &lt;a href="https://docs.polygon.technology/docs/develop/ethereum-polygon/pos/getting-started/"&gt;PoS Bridge&lt;/a&gt;, however, this method is not as secure as using the Plasma Bridge.&lt;/p&gt;

&lt;p&gt;Both these bridges are still secure and safe to use, and in most cases should suit a user’s needs just fine. However, if your project requires state-of-the-art security, it is prudent to consider using Polygon L2 solutions such as &lt;a href="https://polygon.technology/solutions/polygon-zero/"&gt;Zero&lt;/a&gt;, &lt;a href="https://polygon.technology/solutions/polygon-nightfall/"&gt;Nightfall&lt;/a&gt;, and &lt;a href="https://polygon.technology/solutions/polygon-hermez/"&gt;Hermez&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Comparison in Action&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Now that we've seen the advantages that Polygon PoS has over Ethereum for certain projects, let's analyze deployment to both chains.&lt;/p&gt;

&lt;p&gt;In the following sections of this article, we will create a simple NFT contract and deploy it to Polygon Mumbai and Ethereum Goerli testnets. We will observe how the development process for both chains is nearly identical.&lt;/p&gt;

&lt;p&gt;Next, we will analyze NFT contracts that have been deployed previously (by other teams) on Ethereum and Polygon mainnets, and then compare cost and confirmation times.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Overview of the NFT Project&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The project that we're going to create is extremely simple. We want to write and deploy an ERC-721 contract that mints a single NFT to the blockchain of our choice.&lt;/p&gt;

&lt;p&gt;The first step in such projects is to create the NFT art, its associated metadata, and upload it to IPFS. For this tutorial, we have already done this for you.&lt;/p&gt;

&lt;p&gt;You can check out the image uploaded to IPFS &lt;a href="https://gateway.pinata.cloud/ipfs/QmeDadHM1U3jVw1pMpZ5ZENBJhFGafHQeUNTNoapw7j3mq"&gt;here&lt;/a&gt; and the associated NFT metadata &lt;a href="https://gateway.pinata.cloud/ipfs/QmUyZoK21qb8YknXGfDB34RTY8vMqPb6Bsj9U9iLEnyrZR"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Fj2MYJiN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6lgm2gpvg1c0ju1p41sh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Fj2MYJiN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6lgm2gpvg1c0ju1p41sh.png" alt="" width="600" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In case you're interested in learning more about NFT metadata, IPFS, and Pinata, check out this article &lt;a href="https://dev.to/rounakbanik/working-with-nft-metadata-ipfs-and-pinata-3ieh"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Creating the NFT Contract&lt;/strong&gt;
&lt;/h3&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Step 1: Install the MetaMask Extension&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;In case you haven't already, install the &lt;a href="https://metamask.io/download/"&gt;MetaMask extension&lt;/a&gt; for your browser. Once installed, MetaMask will guide you through creating your first wallet.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Step 2: Add Goerli and Mumbai Chains to MetaMask&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;By default, MetaMask comes with the Ethereum mainnet and the Goerli testnet configured. To add the Polygon mainnet and the Mumbai testnet chains, follow the instructions in &lt;a href="https://docs.polygon.technology/docs/develop/metamask/config-polygon-on-metamask/"&gt;this document&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Step 3: Get GoerliETH and Mumbai MATIC from a Faucet&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Head over to Alchemy's &lt;a href="https://goerlifaucet.com/"&gt;Goerli faucet page&lt;/a&gt; and request some free GoerliETH. You may be required to create a free Alchemy account for this.&lt;/p&gt;

&lt;p&gt;If all goes well, you should have 0.05 GoerliETH in your wallet when you switch to the Goerli test network.&lt;/p&gt;

&lt;p&gt;In the same vein, acquire some free Mumbai MATIC from &lt;a href="https://faucet.polygon.technology/"&gt;Polygon's official faucet&lt;/a&gt;. If successful, switching to the Mumbai chain should tell you that you have a balance of 0.2 MATIC.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Step 4: Install NPM and Node&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;We will build our project using JavaScript and node. In case you don't have node and npm installed on your local machine, you can do so &lt;a href="https://nodejs.org/en/download/"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can ensure that everything is working properly by checking the version number of node on your terminal.&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="nv"&gt;$ &lt;/span&gt;node &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;strong&gt;Step 5: Create a Node Project and Install Dependencies&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Let's set up an empty project repository by running the following 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="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;nft-contract &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;nft-contract
&lt;span class="nv"&gt;$ &lt;/span&gt;npm init &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will be using Hardhat, an industry-standard Ethereum development environment, to build and deploy our smart contract. Install Hardhat by running:&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="nv"&gt;$ &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; hardhat
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can now create a sample Hardhat project by running the following command and choosing &lt;strong&gt;Create a basic sample project&lt;/strong&gt;.&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="nv"&gt;$ &lt;/span&gt;npx hardhat
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agree to all the defaults (project root, adding a &lt;code&gt;.gitignore&lt;/code&gt;, and installing all sample project dependencies).&lt;/p&gt;

&lt;p&gt;To check if everything works properly, run:&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="nv"&gt;$ &lt;/span&gt;npx hardhat &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We now have our Hardhat development environment successfully configured. Let us next install the OpenZeppelin contracts package. This will give us access to ERC-721 implementations (the standard for NFTs), on top of which we will build our contract.&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="nv"&gt;$ &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @openzeppelin/contracts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;strong&gt;Step 6: Writing the Smart Contract&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Open the repository in your favorite code editor (e.g. VS Code). In the &lt;code&gt;contracts&lt;/code&gt; folder, create a new file called &lt;code&gt;NFTContract.sol&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We are going to create a very simple ERC-721 contract that mints a single NFT when deployed (i.e. within the constructor). Add the following code to the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight solidity"&gt;&lt;code&gt;&lt;span class="c1"&gt;// SPDX-License-Identifier: MIT
&lt;/span&gt;&lt;span class="k"&gt;pragma&lt;/span&gt; &lt;span class="n"&gt;solidity&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="mf"&gt;0.8&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;contract&lt;/span&gt; &lt;span class="n"&gt;NFTContract&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="n"&gt;ERC721URIStorage&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;ERC721&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Panda NFT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"PNFT"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="c1"&gt;// Mint NFT
&lt;/span&gt;        &lt;span class="n"&gt;_mint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sender&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;// Set metadata
&lt;/span&gt;        &lt;span class="n"&gt;_setTokenURI&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="s"&gt;"ipfs://QmUyZoK21qb8YknXGfDB34RTY8vMqPb6Bsj9U9iLEnyrZR"&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;h4&gt;
  
  
  &lt;strong&gt;Step 7: Deploy the Contract Locally&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Let's now write a script to deploy and test the contract locally. In the scripts folder, create a new file called &lt;code&gt;run.js&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 javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hre&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hardhat&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&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;main&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;contractFactory&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;hre&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;getContractFactory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;NFTContract&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;contractFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;deploy&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;contract&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;deployed&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Contract deployed to:&lt;/span&gt;&lt;span class="dl"&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="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;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&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;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exit&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="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="o"&gt;=&amp;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;error&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;exit&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;Now run the following command on your terminal:&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="nv"&gt;$ &lt;/span&gt;npx hardhat run scripts/run.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;strong&gt;Step 8: Deploy the Contract to Goerli&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;In order to deploy the contract to Goerli, we have to add the network to the &lt;code&gt;hardhat.config.js&lt;/code&gt; file. Replace the &lt;code&gt;module.exports&lt;/code&gt; object at the end of the file with the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;module.exports&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;solidity:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0.8.4"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;networks:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;goerli:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;url:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://ethereum-goerli-rpc.allthatnode.com/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;accounts:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;-- WALLET PRIVATE KEY --&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace the placeholder with your MetaMask wallet's private key. (This can be found in &lt;em&gt;Account Details.&lt;/em&gt;) Take care to never share this key or file publicly.&lt;/p&gt;

&lt;p&gt;To deploy to the Goerli testnet, run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;npx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;hardhat&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;run&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;scripts/run.js&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;--network&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;goerli&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If all goes well, your terminal will display the address of the deployed contract on the Goerli network. Head over to &lt;a href="https://goerli.etherscan.io/"&gt;https://goerli.etherscan.io&lt;/a&gt; and search for your contract address to view your contract.&lt;/p&gt;

&lt;p&gt;You can find the contract that we deployed &lt;a href="https://goerli.etherscan.io/address/0x64ccE52898F5d61380D2Ec8C02F2EF16F28436de"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Step 9: Deploy the Contract to Mumbai&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Let's now deploy our contract to the Polygon Mumbai network. The best part of this step is that we have to change &lt;strong&gt;absolutely nothing&lt;/strong&gt; in our contract or the run script. The only thing we need to add is the &lt;code&gt;mumbai&lt;/code&gt; network to &lt;code&gt;hardhat.config.js&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;module.exports&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;solidity:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0.8.4"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;networks:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;goerli:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;url:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://ethereum-goerli-rpc.allthatnode.com/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;accounts:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;-- WALLET PRIVATE KEY --&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;mumbai:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;url:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://rpc-mumbai.maticvigil.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;accounts:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;-- WALLET PRIVATE KEY --&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Deploy to Mumbai by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx hardhat run scripts/run.js &lt;span class="nt"&gt;--network&lt;/span&gt; mumbai
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can search for your contract address at &lt;a href="https://mumbai.polygonscan.com/"&gt;https://mumbai.polygonscan.com&lt;/a&gt;. You can find our contract &lt;a href="https://mumbai.polygonscan.com/address/0x785e970C281ecFCBbc83b1CA1b32Fb30BA0E08B3"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can also search for your Goerli and Mumbai NFTs on &lt;a href="https://testnets.opensea.io/"&gt;OpenSea Testnets&lt;/a&gt;. For example, &lt;a href="https://testnets.opensea.io/assets/mumbai/0x785e970c281ecfcbbc83b1ca1b32fb30ba0e08b3/0"&gt;here&lt;/a&gt; is the NFT we minted on the Mumbai network.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Comparing Cost and Time&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;By now, it should be abundantly clear that developing for Ethereum and the Polygon sidechain is nearly identical.&lt;/p&gt;

&lt;p&gt;But what are the cost and time implications?&lt;/p&gt;

&lt;p&gt;We won't be able to answer these questions with the contracts we deployed since we were operating on testnets using fake money.&lt;/p&gt;

&lt;p&gt;But not to worry. We have deployed these contracts to the Ethereum and Polygon mainnets on your behalf. Let’s take a look at the performance.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Ethereum&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;You can check out the deployed NFT contract on Ethereum &lt;a href="https://etherscan.io/address/0x5acea83cd77703773429959e66cc2c2f648262a7"&gt;here&lt;/a&gt; and the contract creation transaction &lt;a href="https://etherscan.io/tx/0x26ac19375af708c7d7b9266d9aae9198f49b41124f49af68dc1d28963f6363af"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Despite the recent drops in Ethereum prices (in terms of USD) and average gas prices (in terms of gwei), you can see that contract deployment cost around &lt;strong&gt;0.02 ETH or $40&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The time to confirm this Ethereum transaction was &lt;strong&gt;approximately 40 seconds.&lt;/strong&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Polygon&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;You can check out the deployed NFT contract on Polygon &lt;a href="https://polygonscan.com/address/0xceb61fdf7130d170c50c02e3a9bed4eb83b42a46"&gt;here&lt;/a&gt; and the contract creation transaction &lt;a href="https://polygonscan.com/tx/0x95c2bbbb79ab07db7ea656b0506c88bd3f3e83e485e1d075f770581f312ffd06"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Notice that we paid 0.06 MATIC when MATIC was trading at $0.94. Therefore, we paid &lt;strong&gt;$0.06 to deploy the contract&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The time to confirm this transaction was &lt;strong&gt;6 seconds&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In essence, this contract was confirmed almost &lt;strong&gt;7 times faster and with a cost reduction of 1000x&lt;/strong&gt;!&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Ethereum is easily the most important smart contract blockchain in existence. However, it faces huge obstacles when it comes to scale and transaction costs.&lt;/p&gt;

&lt;p&gt;Hopefully, this article has made a strong case for why Polygon is an excellent panacea to Ethereum's scalability problems. By operating as a PoS sidechain, it significantly increases processing speeds and reduces costs.&lt;/p&gt;

&lt;p&gt;For Ethereum developers, building on Polygon requires almost zero additional upskilling. Ethereum tools are compatible with both environments. To start  building on Polygon, check out the documentation &lt;a href="https://docs.polygon.technology/docs/develop/getting-started/"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>web3</category>
      <category>ethereum</category>
      <category>polygon</category>
      <category>nft</category>
    </item>
    <item>
      <title>No-Code: Buy Me a Coffee With Coinbase!</title>
      <dc:creator>Paul McAviney</dc:creator>
      <pubDate>Tue, 19 Jul 2022 15:40:43 +0000</pubDate>
      <link>https://forem.com/0xpaulie/no-code-buy-me-a-coffee-with-coinbase-34pn</link>
      <guid>https://forem.com/0xpaulie/no-code-buy-me-a-coffee-with-coinbase-34pn</guid>
      <description>&lt;p&gt;&lt;strong&gt;Summary:&lt;/strong&gt; How I easily installed a &lt;em&gt;Buy Me A Coffee&lt;/em&gt; type feature on my website to accept crypto donations, using minimal code.&lt;/p&gt;

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

&lt;p&gt;I never thought of myself as a writer. However, it turns out I actually have a knack for it! Learning new technology and then writing about it helps me solidify the concepts. As an added bonus, I’m able to help teach others on the same path as me. Creating technical content is fun! Eating cheap, frozen dinners every night is not. So how can I start accepting payment for all the hard work I’m putting in?&lt;/p&gt;

&lt;p&gt;Some of my readers suggested I build a “&lt;em&gt;Buy Me A Coffee&lt;/em&gt;” type feature on my website. This simple method to start accepting crypto donations could be my answer to move from frozen dinners to fresh produce!  &lt;/p&gt;

&lt;p&gt;This article will explain how I installed a method to receive crypto donations using no-code solutions by Coinbase Commerce. Then, we’ll build a simple project so you can see just how easy it is and how little code is involved.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem: Broke But Still Building
&lt;/h2&gt;

&lt;p&gt;I tell my &lt;a href="https://blog.paulmcaviney.ca/"&gt;readers&lt;/a&gt; and &lt;a href="https://twitter.com/paul_can_code"&gt;Twitter followers&lt;/a&gt; all the time that creating content around web3 tech is one of the best ways to learn it. Writing about something quickly points out any gaps in your knowledge. It’s a fast track to understanding these complicated networks and how they operate at a technical level. However, what I don’t tell them is that when you’re first starting out, writing technical articles doesn’t exactly pay the bills if you don’t have any clients yet.&lt;/p&gt;

&lt;p&gt;Clients or not, helping others learn through content creation is rewarding. One of my favorite aspects of being a technical writer is when a reader reaches out saying that I helped them solve a problem or learn something new. Some of these readers even expressed interest in returning the favor. They suggested I build a “&lt;em&gt;Buy Me A Coffee&lt;/em&gt;” type feature on my website. This seemed like an excellent way to get paid for the hard work I put into my content.&lt;/p&gt;

&lt;p&gt;Building a feature like this from scratch sounds like a nightmare, though. I don’t have time to improve my frontend skills to do this properly; I just want to focus on web3 stuff! So I started looking for an easier solution—and found one with &lt;a href="https://docs.cloud.coinbase.com/commerce/docs"&gt;Coinbase Commerce&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Uevs_Pnf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8sss9rk9ypqtsrml6tbm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Uevs_Pnf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8sss9rk9ypqtsrml6tbm.png" alt="" width="629" height="481"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution: No-Code With Coinbase Commerce
&lt;/h2&gt;

&lt;p&gt;Coinbase Commerce has easy-to-install payment gateways that make it simple to accept crypto. I can use this to create a “&lt;em&gt;Buy Me A Coffee&lt;/em&gt;” feature on my site, no problem!&lt;/p&gt;

&lt;p&gt;As a plus, I’m already familiar with Coinbase. I’ve been trading cryptocurrencies since 2017, and Coinbase was the first crypto exchange I ever signed up for.&lt;/p&gt;

&lt;p&gt;Installing the donation gateway was easy. All I had to do was create the gateway in my Coinbase Commerce dashboard and then copy the code it generated onto my site. Then with only minor adjustments to the code, I got it to look how I wanted. Now I’m ready to start accepting crypto donations so I can hopefully treat myself to something a little better than frozen pizzas.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lTMO7BuP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pdr4jj60zxq4mkgmxupb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lTMO7BuP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pdr4jj60zxq4mkgmxupb.png" alt="" width="880" height="216"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Install a Crypto Donations Button
&lt;/h2&gt;

&lt;p&gt;For the rest of the article, we’ll run through creating a crypto donations button to show you just how easy it is. We’ll go through it step by step, so even if you’re not a developer, you’ll be able to start accepting crypto in minutes&lt;/p&gt;







&lt;h3&gt;
  
  
  What You’ll Learn
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;How to easily install a link on your website to start accepting crypto donations&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What You’ll Need
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;a href="https://commerce.coinbase.com/"&gt;Coinbase Commerce account&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;The &lt;a href="https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2&amp;amp;gl=US"&gt;Google Authenticator App&lt;/a&gt; on your phone (for 2-step account verification)&lt;/li&gt;
&lt;li&gt;A website to install your link on&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Additional Resources
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://commerce.coinbase.com/docs/"&gt;Coinbase Commerce Docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;







&lt;h3&gt;
  
  
  Step 1 - Set Up a Coinbase Commerce Account
&lt;/h3&gt;

&lt;p&gt;The first step in getting a button to accept crypto donations is to set up a Coinbase Commerce account. Head to &lt;a href="https://commerce.coinbase.com/"&gt;https://commerce.coinbase.com/&lt;/a&gt; and select the &lt;strong&gt;Get Started&lt;/strong&gt; button. Follow the steps to get everything set up correctly.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Choose the &lt;em&gt;Self managed&lt;/em&gt; option to get started with just an email address.&lt;/li&gt;
&lt;li&gt;Verify your account through email.&lt;/li&gt;
&lt;li&gt;Set up 2-step verification using the &lt;a href="https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2&amp;amp;gl=US"&gt;Google Authenticator&lt;/a&gt; app on your phone.&lt;/li&gt;
&lt;li&gt;Set up a Coinbase Crypto Wallet. 

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;IMPORTANT!&lt;/em&gt;&lt;/strong&gt;– Write down your seed phrase somewhere safe! Anyone with this seed phrase can empty your wallet!&lt;/li&gt;
&lt;li&gt;Verify your seed phrase in the next step. &lt;/li&gt;
&lt;li&gt;Lastly, you can save an encrypted version of your wallet to Google Drive if you want, but it’s not necessary.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After completing all the above steps, go to your new dashboard!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nN8EWz7Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cazrqhu36uvsj9p32rl8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nN8EWz7Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cazrqhu36uvsj9p32rl8.png" alt="" width="880" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2 - Whitelist Your Website
&lt;/h3&gt;

&lt;p&gt;Now that you have a place to send any funds you may receive, the next step is to add your website to the whitelist. This just means adding your website to a list of approved websites that are allowed to host your new payment button. You wouldn’t want just anyone installing it wherever they want!&lt;/p&gt;

&lt;p&gt;Click on your email address in the top right corner of the screen and select &lt;strong&gt;Settings&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RzTMwj3T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uxru4qsijzf3qzmmtj8c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RzTMwj3T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uxru4qsijzf3qzmmtj8c.png" alt="" width="463" height="497"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, select the &lt;strong&gt;Security&lt;/strong&gt; tab and click on the &lt;strong&gt;Whitelist a domain&lt;/strong&gt; button. Enter the full URL of your website, including the &lt;code&gt;https://&lt;/code&gt; part. If this is successful, you will now see it in the list of approved sites.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--g-PKhUOd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r2ja75w7y48a2i449fsk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--g-PKhUOd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r2ja75w7y48a2i449fsk.png" alt="" width="880" height="147"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; If you are a developer testing on a locally hosted instance of your website, you do not need to whitelist &lt;code&gt;localhost&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3 - Create a Checkout
&lt;/h3&gt;

&lt;p&gt;The next step is to create the payment gateway your donate button will send the user to. Click on the &lt;strong&gt;Checkouts&lt;/strong&gt; tab on the left-hand side of the screen, then select &lt;strong&gt;Create a checkout&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eds7SRTY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zfpgxzxep0a41r93066o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eds7SRTY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zfpgxzxep0a41r93066o.png" alt="" width="236" height="411"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fill in the details for your checkout, giving it a name, description, and image if you’d like. Then, select &lt;strong&gt;Let your visitors choose&lt;/strong&gt; under the &lt;strong&gt;"What kind of pricing do you want to offer?”&lt;/strong&gt; heading to accept donations. You can also ask for additional information from the person donating, but this is optional.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--G1kTuk-u--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ffiytb1g1bzvgkibdx0m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--G1kTuk-u--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ffiytb1g1bzvgkibdx0m.png" alt="" width="880" height="170"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you have filled in the details, click on the &lt;strong&gt;Create checkout&lt;/strong&gt; button at the bottom to finish. A popup will display some options for you to share your new checkout.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--j5U4RhT_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8cpwbs8pqjng0g6tiztm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--j5U4RhT_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8cpwbs8pqjng0g6tiztm.png" alt="" width="627" height="569"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can &lt;strong&gt;share&lt;/strong&gt; your checkout link directly, &lt;strong&gt;copy the code&lt;/strong&gt; to create the Donation Button on your website, or select &lt;strong&gt;View checkout&lt;/strong&gt; to see it in action.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4 - Add the Code to Your Website
&lt;/h3&gt;

&lt;p&gt;The final step is to place the checkout code on your website. So navigate to your &lt;code&gt;index.html&lt;/code&gt; or whichever page you want to put the button on and paste the code where it makes sense for you. For example, I added mine to the bottom of my hero section and changed the Button text to say “Buy Me A Coffee”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_4iLJa8J--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0szqs06mgws6uwtln8o3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_4iLJa8J--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0szqs06mgws6uwtln8o3.png" alt="" width="703" height="875"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now clicking on the Donate button will send any charitable users to your shiny, new checkout page where they can donate as much as they like in multiple cryptocurrencies. Here’s what mine looks like: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mqg6Ijzo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d9tetu41xuz4kvrfmhfw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mqg6Ijzo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d9tetu41xuz4kvrfmhfw.png" alt="" width="880" height="434"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Creating web3 technical content is challenging, yet rewarding. Any newcomer will see that it is a fast way to learn concepts quickly. However, they will also learn that being a content creator takes a while to start being a profitable career choice. This is where a “&lt;em&gt;Buy Me A Coffee&lt;/em&gt;” button helps a lot.&lt;/p&gt;

&lt;p&gt;This no-code solution makes things simple for anyone to make a crypto payment gateway in minutes. Now that I’ve got this fancy, new feature on my website, I can start accepting donations for all the hard work I put into creating content! No more frozen dinners for this guy! I’m moving up in the world!&lt;/p&gt;

&lt;p&gt;If this article has helped you, maybe &lt;a href="https://commerce.coinbase.com/checkout/7acfc6cf-bfe3-4e0e-bbd0-7f10dc4d9cb5"&gt;Buy Me A Coffee&lt;/a&gt;? ;)&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Using Infura’s NFT API With Lootbox</title>
      <dc:creator>Paul McAviney</dc:creator>
      <pubDate>Thu, 07 Jul 2022 20:59:10 +0000</pubDate>
      <link>https://forem.com/0xpaulie/using-infuras-nft-api-with-lootbox-pp</link>
      <guid>https://forem.com/0xpaulie/using-infuras-nft-api-with-lootbox-pp</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;I’ve only been in Web3 for about a year now, but I can honestly say that NFTs are the most exciting aspect about it for me. I’m not talking about Apes or Punks, however. PFP (profile picture) projects and art, although cool and a simple proof of concept for the technology, won’t create a better world. &lt;/p&gt;

&lt;p&gt;Instead, I’m excited about the actual utility of NFTs. Allowing gamers to own their assets, delivering fair royalty commissions to musicians and artists, and making concert tickets impossible to scalp while providing a sweet digital memento are some of the use cases I find interesting.&lt;/p&gt;

&lt;p&gt;However, building and interacting with NFTs aren’t always the easiest thing to do. As developers, we need clear resources to build projects effectively in order to give our users a better experience. &lt;/p&gt;

&lt;p&gt;I recently heard about &lt;a href="https://infura.io/resources/apis/nft-api-beta-signup" rel="noopener noreferrer"&gt;Infura’s private beta for their NFT API&lt;/a&gt;, so I thought I would check it out and see how it could improve my development workflow. In this article, I will explore the capabilities of Infura’s NFT API and test it out using a Lootbox NFT sample project from Infura’s Github.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is the Infura NFT API?
&lt;/h2&gt;

&lt;p&gt;According to &lt;a href="https://blog.infura.io/post/introducing-the-infura-nft-api-beta-release" rel="noopener noreferrer"&gt;this blog post&lt;/a&gt; on Infura’s website, the NFT API will help me “accelerate my time to value” and allow me to interact with anything related to NFTs through a convenient SDK. In addition, I can build and verify my NFTs, create metadata templates and easily mint NFTs. So my first impression is that I can start creating and interacting with NFTs using API endpoints rather than building smart contracts and deploying them.&lt;/p&gt;

&lt;p&gt;Sounds pretty useful! And I’m all for testing any tool that will help improve my development processes. Infura’s NFT API suite seems helpful for any dev transitioning from Web2, since you can run API endpoints without Solidity.  &lt;/p&gt;

&lt;p&gt;Now let’s dive deeper and see what this NFT API is capable of.&lt;/p&gt;

&lt;h2&gt;
  
  
  Infura NFT API Capabilities
&lt;/h2&gt;

&lt;p&gt;A quick glance through the &lt;a href="https://docs.infura.io/infura/features/nft-sdk" rel="noopener noreferrer"&gt;NFT API documentation&lt;/a&gt; on Infura’s website proves my first impression correct. I will be able to deploy and call methods on my NFT contracts using Infura’s API endpoints, without having to actually write the smart contract code. This is a huge time saver! &lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.infura.io/infura/features/nft-sdk/how-to/deploy-a-contract" rel="noopener noreferrer"&gt;Deploying a contract&lt;/a&gt; is straightforward. I create the NFT metadata in JSON format, &lt;a href="https://docs.infura.io/infura/networks/ipfs/how-to/make-requests" rel="noopener noreferrer"&gt;upload the metadata to IPFS&lt;/a&gt; in another Infura project, then create a simple deployment script and run it with node. I also have to make a &lt;code&gt;.env&lt;/code&gt; file to hold some environment variables. My deployment script ends up looking something like this:&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;config&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;loadEnv&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;dotenv&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;SDK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Auth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;TEMPLATES&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;@infura/sdk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;loadEnv&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;auth&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;Auth&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;projectId&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;INFURA_PROJECT_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;secretId&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;INFURA_PROJECT_SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;privateKey&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;WALLET_PRIVATE_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;chainId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&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;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;SDK&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;auth&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;myNFTContract&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;deploy&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
   &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TEMPLATES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ERC721Mintable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="na"&gt;params&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="s1"&gt;My NFT Contract&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="na"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MYNFT&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="na"&gt;contractURI&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://MY_NFT_METADATA_URL&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;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="s2"&gt;`Contract address is: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;myNFTContract&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contractAddress&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, I run it with Node. Infura creates a smart contract for me and uploads it to Ethereum behind the scenes. After that, I just need to make sure I have some tokens for whichever &lt;code&gt;chainId&lt;/code&gt; I have specified in my code. In this case, the Rinkeby testnet (chainId: 4). From here, I could &lt;a href="https://docs.infura.io/infura/features/nft-sdk/how-to/mint-an-nft" rel="noopener noreferrer"&gt;mint NFTs&lt;/a&gt; from this contract or gather the contract metadata. &lt;/p&gt;

&lt;p&gt;This is a much easier method to create an NFT contract than writing Solidity code and deploying it myself!&lt;/p&gt;

&lt;p&gt;The NFT API also provides methods for &lt;a href="https://docs.infura.io/infura/features/nft-sdk/how-to/get-nft-information" rel="noopener noreferrer"&gt;gathering NFT info&lt;/a&gt; from wallets, &lt;a href="https://docs.infura.io/infura/features/nft-sdk/how-to/transfer-an-nft" rel="noopener noreferrer"&gt;transferring NFTs&lt;/a&gt; from one wallet to another, and a host of other &lt;a href="https://docs.infura.io/infura/features/nft-sdk/apis/javascript-api/templates/erc721mintable-methods" rel="noopener noreferrer"&gt;NFT methods&lt;/a&gt;. These include &lt;a href="https://docs.infura.io/infura/features/nft-sdk/apis/javascript-api/templates/erc721mintable-methods/addminter" rel="noopener noreferrer"&gt;adding an address to the minter list&lt;/a&gt;, &lt;a href="https://docs.infura.io/infura/features/nft-sdk/apis/javascript-api/templates/erc721mintable-methods/setroyalties" rel="noopener noreferrer"&gt;setting royalty info&lt;/a&gt;, and &lt;a href="https://docs.infura.io/infura/features/nft-sdk/apis/javascript-api/templates/erc721mintable-methods/setcontracturi" rel="noopener noreferrer"&gt;changing the contract URI&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Overall, it seems that Infura’s NFT API indeed helps improve my development workflow. Having all the necessary functionality for building and interacting with NFTs packaged together in an easy-to-use SDK is quite convenient!&lt;/p&gt;

&lt;p&gt;But enough about what it can do, let’s see how this API works!&lt;/p&gt;

&lt;h2&gt;
  
  
  The Lootbox Project
&lt;/h2&gt;

&lt;p&gt;Along with the NFT API, Infura released an &lt;a href="https://github.com/INFURA/nft-api-lootbox-gallery-app" rel="noopener noreferrer"&gt;NFT Gallery Project on their Github&lt;/a&gt; to demo its capabilities. All I will have to do is input an Infura project ID and secret, then connect my MetaMask wallet to the dapp frontend. Then the dapp uses the API to fetch all my NFTs to display nicely in the frontend. So to break that down, I will need the following things for this project:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An &lt;a href="https://infura.io/" rel="noopener noreferrer"&gt;Infura account&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Infura Project ID and Secret&lt;/li&gt;
&lt;li&gt;A &lt;a href="https://metamask.io/" rel="noopener noreferrer"&gt;MetaMask wallet extension&lt;/a&gt; with NFTs in it &lt;/li&gt;
&lt;/ul&gt;

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

&lt;h3&gt;
  
  
  Step 1 - The Infura Project ID and Secret
&lt;/h3&gt;

&lt;p&gt;Before starting the Lootbox project, I want to gather the necessary items. So first, I’ll head to &lt;a href="https://infura.io/" rel="noopener noreferrer"&gt;infura.io&lt;/a&gt;, log in, and create a new project. Then, I can grab the &lt;strong&gt;Project ID&lt;/strong&gt; and &lt;strong&gt;Project Secret&lt;/strong&gt; for use later.&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%2Fmpitdczalk2hzfo9g4qa.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%2Fmpitdczalk2hzfo9g4qa.png" alt="A new project dialogue box on Infura"&gt;&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcnjbs888t2jyc2oni5ak.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%2Fcnjbs888t2jyc2oni5ak.png" alt="The project ID and project secrets, highlighted in red, showing the reader where to copy from"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2 - MetaMask
&lt;/h3&gt;

&lt;p&gt;This step will be quick because I already have the extension installed in my browser. If someone following along with this article doesn’t, however, head to &lt;a href="https://metamask.io/" rel="noopener noreferrer"&gt;metamask.io&lt;/a&gt; and &lt;a href="https://metamask.io/download/" rel="noopener noreferrer"&gt;download&lt;/a&gt; the extension for your specific browser. Then follow the steps to create a new account.&lt;/p&gt;

&lt;p&gt;Next, I’ll sign in and switch accounts to the wallet address that holds my NFTs. If you need to acquire an NFT, you can head to &lt;a href="https://looksrare.org/" rel="noopener noreferrer"&gt;your favorite marketplace&lt;/a&gt; and buy one or try to create one yourself using the Infura NFT API 😉. Either way, you will need some ETH in your wallet.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3 - Setting Up The Project
&lt;/h3&gt;

&lt;p&gt;With all the prep work out of the way, I can start building the project. So next, I’ll clone the project repo onto my local machine. I’ll first navigate to the folder I want to work out of and then type 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;git clone https://github.com/INFURA/nft-api-lootbox-gallery-app.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, I will change directories into the project folder and install dependencies using &lt;a href="https://classic.yarnpkg.com/lang/en/docs/install/#windows-stable" rel="noopener noreferrer"&gt;yarn&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;&lt;span class="nb"&gt;cd &lt;/span&gt;nft-api-lootbox-gallery-app
yarn
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After everything is installed, the last thing I need to do is create a &lt;code&gt;.env&lt;/code&gt; file to store my environment variables and secrets. I’ll just copy the file that’s already there and add my variables to it.&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;cp&lt;/span&gt; .env .env.local 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now I’ll open up the project and add my &lt;strong&gt;Project ID&lt;/strong&gt; and &lt;strong&gt;Project Secret&lt;/strong&gt; from my recently created Infura project. There’s also an option to input the Account Address of any wallet to view their NFTs, but I’ve got my own I want to see in the Lootbox NFT Gallery.&lt;/p&gt;

&lt;p&gt;With all the setup out of the way, I can finally run the Lootbox project. But first, I want to browse through the code to see what’s happening under the hood.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4 - The Lootbox Code
&lt;/h3&gt;

&lt;p&gt;Based on the &lt;a href="https://github.com/INFURA/nft-api-lootbox-gallery-app#readme" rel="noopener noreferrer"&gt;README file&lt;/a&gt; of the Lootbox project, the most important components are in the &lt;code&gt;pages/index.tsx&lt;/code&gt;, &lt;code&gt;hooks/useWallet.ts&lt;/code&gt;, and &lt;code&gt;pages/api/assets.ts&lt;/code&gt; files. So I’m going to browse those and see if I can figure out how this project uses the Infura NFT API.&lt;/p&gt;

&lt;p&gt;After looking through these files, I can see the &lt;code&gt;pages/index.tsx&lt;/code&gt; file contains the code which displays the frontend for the project. If the &lt;code&gt;showGallery&lt;/code&gt; state variable is true, then it should display my NFTs. If it’s false, then it should display the welcome text with the &lt;strong&gt;Connect Wallet&lt;/strong&gt; button. This Connect Wallet button connects to some functions in the &lt;code&gt;hooks/useWallet.ts&lt;/code&gt; file, so I’ll check there next.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;hooks/useWallet.ts&lt;/code&gt; file, I can see the function which is supposed to grab my NFTs. Specifically, the &lt;code&gt;getTokens&lt;/code&gt; 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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getTokens&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;accountAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&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;try&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;data&lt;/span&gt; &lt;span class="p"&gt;}&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;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/assets&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="nx"&gt;accountAddress&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;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assets&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="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;setTimeout&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="nf"&gt;setErrorMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error getting 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="mi"&gt;2000&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="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function seems to make a POST request using a parameter from the &lt;code&gt;/api/assets&lt;/code&gt; file and return the results with my assets. So looking into the &lt;code&gt;pages/api/assets.ts&lt;/code&gt; file, I can see where the NFT API is being used.&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;try&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;data&lt;/span&gt; &lt;span class="p"&gt;}&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;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;  &lt;span class="s2"&gt;`https://nft.api.infura.io/networks/1/accounts/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;accountAddress&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/assets/nfts`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
        &lt;span class="na"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;username&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;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;INFURA_PROJECT_ID&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="na"&gt;password&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;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;INFURA_PROJECT_SECRET&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;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;assets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assets&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;This code calls the &lt;a href="https://docs.infura.io/infura/features/nft-sdk/apis/javascript-api/sdk/getnfts" rel="noopener noreferrer"&gt;get function of the NFT API&lt;/a&gt;, using my &lt;code&gt;Infura Project ID&lt;/code&gt; and &lt;code&gt;Project Secret&lt;/code&gt; to access my account, and returns my NFTs in a JSON object. Following the path back to the &lt;code&gt;pages/index.tsx&lt;/code&gt; file, if the &lt;code&gt;getTokens&lt;/code&gt; function from &lt;code&gt;hooks/useWallet.ts&lt;/code&gt; doesn’t timeout, it will return my NFTs, switch the &lt;code&gt;setGallery&lt;/code&gt; state variable to &lt;code&gt;true&lt;/code&gt;, and display my NFTs on the page.&lt;/p&gt;

&lt;p&gt;Cool! So I’ve got an idea of how it works, let’s see it in action!&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5 - Running The Lootbox Project
&lt;/h3&gt;

&lt;p&gt;To run the project locally, I just need to type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After navigating to &lt;a href="http://localhost:3000/" rel="noopener noreferrer"&gt;http://localhost:3000/&lt;/a&gt;, I can see a nice-looking frontend for the Lootbox Project.&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%2F7b1nh8cfbhesd72t1ork.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%2F7b1nh8cfbhesd72t1ork.png" alt="The Lootbox project main page displays the title "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Clicking on &lt;strong&gt;Connect Wallet&lt;/strong&gt; prompts my MetaMask wallet to pop up to approve the connection request.&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%2Fem3or1gk7s7ggkdphhfy.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%2Fem3or1gk7s7ggkdphhfy.png" alt="MetaMask pops up, prompting me to connect my wallet"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After connecting, it immediately starts fetching my tokens. This is the point where I now know the dapp is using the NFT API.&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%2Frt5bkflmjdnvq4nr3dlc.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%2Frt5bkflmjdnvq4nr3dlc.png" alt="It says: "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the fetch is successful, it displays my NFTs in a fancy gallery, allowing me to browse and choose each one to get a better look at them. Neat!&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%2Fayvwgl5rnn34zb9zykba.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%2Fayvwgl5rnn34zb9zykba.png" alt="My NFTs displayed successfully"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;My verdict on the Infura NFT API is that it's a tool that cuts down my development time, and there’s quite a bit I can do with it. It’s handy to build, mint, and interact with NFTs from an easy-to-use API. Although I am more familiar with building NFT contracts with Solidity and deploying them with Truffle, I can easily see how this would help smooth the transition of a Web2 dev into Web3. Using JavaScript rather than writing a smart contract will be a huge time saver for many Web2 developers.&lt;/p&gt;

&lt;p&gt;I would suggest trying the NFT API out for yourself. It’s still in private beta, but anyone can &lt;a href="https://infura.io/resources/apis/nft-api-beta-signup" rel="noopener noreferrer"&gt;register&lt;/a&gt;. For more information on its capabilities, you can check out &lt;a href="https://www.youtube.com/watch?v=ERV_FbCDBIQ" rel="noopener noreferrer"&gt;this YouTube demo&lt;/a&gt; or &lt;a href="https://docs.infura.io/infura/features/nft-sdk" rel="noopener noreferrer"&gt;Infura’s documentation&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>web3</category>
      <category>blockchain</category>
      <category>nft</category>
      <category>ethereum</category>
    </item>
    <item>
      <title>Accessing Ethereum Archive Nodes with Infura</title>
      <dc:creator>Paul McAviney</dc:creator>
      <pubDate>Wed, 01 Jun 2022 15:18:52 +0000</pubDate>
      <link>https://forem.com/0xpaulie/accessing-ethereum-archive-nodes-with-infura-op9</link>
      <guid>https://forem.com/0xpaulie/accessing-ethereum-archive-nodes-with-infura-op9</guid>
      <description>&lt;h3&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Archive nodes are particular nodes on the Ethereum Network that store historical blockchain data. Because they offer this historical information, they are helpful when you need to audit past transaction history or gather data. Services like &lt;a href="https://etherscan.io/"&gt;Etherscan&lt;/a&gt; and &lt;a href="https://docs.dune.xyz"&gt;Dune Analytics&lt;/a&gt; use archive nodes, but anyone can run one themselves. &lt;/p&gt;

&lt;p&gt;In this article, we will review the different types of Ethereum nodes, dive deeper into Archive Nodes, and introduce the new archive node capabilities of Infura. We’ll then walk through a real-world project to show how to connect the Infura API and web3.js to a pre-built react frontend. Once complete, the user will be able to query an Archive Node for some statistics for a given Ethereum wallet address.&lt;/p&gt;

&lt;h3&gt;
  
  
  Table of Contents
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;What are Ethereum Nodes?&lt;/li&gt;
&lt;li&gt;Types of Ethereum Nodes&lt;/li&gt;
&lt;li&gt;Archive Nodes&lt;/li&gt;
&lt;li&gt;Archive Node Providers&lt;/li&gt;
&lt;li&gt;The Project&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;What Are Ethereum Nodes?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In simple terms, a node is just a connection point in a network. However, in the case of Ethereum, different types of nodes hold various responsibilities to the network.&lt;/p&gt;

&lt;p&gt;The Ethereum blockchain operates on what is called the &lt;a href="https://ethereum.org/en/developers/docs/evm/"&gt;Ethereum Virtual Machine&lt;/a&gt; (EVM), which is a type of decentralized &lt;a href="https://etherscan.io/nodetracker"&gt;global&lt;/a&gt; computer. Nodes, in this case, provide the processing power for this computer. They serve requested data, create and validate blocks, store transaction data or smart contract code, and much more. Anyone with the required hardware can download an &lt;a href="https://ethereum.org/en/developers/docs/nodes-and-clients/#execution-clients"&gt;Ethereum client&lt;/a&gt; and spin up their own node to participate in the network. This also prevents any single entity from controlling the entire network and contributes to Ethereum’s decentralization.&lt;/p&gt;

&lt;p&gt;There are four main types of Ethereum nodes, each contributing to the network differently. Together they relay information to other nodes, verify transactions and the EVM state, and provide the infrastructure needed to keep the Ethereum Network operating efficiently. They communicate with one another to ensure they all agree on the state of the network. Therefore, having more nodes makes the network stronger and more resilient to &lt;a href="https://www.investopedia.com/terms/1/51-attack.asp"&gt;attacks&lt;/a&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Types of Ethereum Nodes&lt;/strong&gt;
&lt;/h3&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Full Node&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Full Nodes verify transactions and EVM state, validate blocks, launch and execute smart contract code, and can serve network data when requested. They also store the state of the Ethereum Blockchain up to the most recent 128 blocks but can build an archive of historical states on demand.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Mining Node (Commonly referred to as a “Miner”)&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;A Miner is a Full Node running a &lt;a href="https://ethereum.org/en/developers/docs/consensus-mechanisms/pow/mining/"&gt;mining client&lt;/a&gt;. In its present state, Ethereum provides consensus through the &lt;a href="https://ethereum.org/en/developers/docs/consensus-mechanisms/pow/"&gt;proof-of-work&lt;/a&gt; algorithm. To summarize, this means a mining node competes in a computation race with other mining nodes to create the next block. Once created, the new block is broadcast to the network to be verified by other nodes and appended to the end of the blockchain.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Light Node&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;A Light Node is a “light” version of a Full Node, which only contains block header data such as the previous block’s hash and a timestamp rather than the block data in its entirety. They make on-demand requests to Full Nodes and only validate certain pieces of state as required by their users. Example uses are to check balances, verify if a transaction was confirmed, check event logs, and do other light-duty tasks. Light Nodes can be easily run by lower-capacity devices such as a mobile phone or RaspberryPi.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Archive Node&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;An Archive Node is a type of Full Node that is running in “archive mode”. They contain all the same data as a Full Node but also all the historical state data of the entire blockchain since &lt;a href="https://etherscan.io/block/0"&gt;Genesis Block&lt;/a&gt;. We’ll focus on archive nodes for the remainder of this article.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;More on Archive Nodes&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Although Full Nodes can rebuild historical blockchain state data, this process is &lt;a href="https://geth.ethereum.org/docs/dapp/tracing"&gt;slow and inefficient&lt;/a&gt;. Depending on the use case, this data may need to be served up quickly. This is where Archive Nodes come in. Because Archive Nodes contain historical data from the very first block, they can easily trace any arbitrary transaction at any time.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Why Access an Archive Node?&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;If there is information you need to get from the Ethereum Blockchain before the most recent 128 blocks, the most efficient way to get this is through an Archive Node. Some of this information may include account balances, smart contract code, transaction counts, or the value at a particular storage position. They also enable the testing of smart contract code without creating a transaction on the blockchain.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Specs to Run an Archive Node&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Running your own node means having more control of the information you share with the blockchain. You can create more secure and private dApps (decentralized apps), and your addresses and balances won’t leak to random nodes on the network. Running an Archive Node also means quick access to historical blockchain data without signing up for any third-party services.&lt;/p&gt;

&lt;p&gt;These are the specifications you would need to be able to &lt;a href="https://ethereum.org/en/run-a-node/"&gt;run your own Ethereum Archive Node&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A CPU with at least four cores&lt;/li&gt;
&lt;li&gt;16 GB or more of RAM&lt;/li&gt;
&lt;li&gt;An SSD drive with at least 6 TB of space&lt;/li&gt;
&lt;li&gt;At least 25 MBit/s bandwidth&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As you can see, the requirements to spin up an Archive Node make it reasonably accessible. Not exactly cheap, but still within reach to an individual. It does require some technical know-how and constant upkeep though. If you don’t have the time, drive, or equipment to run your own, a Node Provider is a great alternative.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Archive Node Providers&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Node Providers make it simple for anyone to access and interact with the Ethereum Blockchain through their easy-to-use APIs. All you need to do is create a new project and then easily call &lt;a href="https://www.wallarm.com/what/what-is-json-rpc"&gt;JSON RPC&lt;/a&gt; methods with the URL they provide.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Infura&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Infura is arguably the most popular Node Provider in the space. It was created by ConsenSys, the team behind MetaMask and the Truffle blockchain development framework. They’ve been around for a while, and their services are great for beginners and organizations looking to scale.  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now has free Archive Node Access&lt;/li&gt;
&lt;li&gt;Great &lt;a href="https://infura.io/pricing"&gt;free pricing tier&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Offers access to Layer 2 scaling solutions&lt;/li&gt;
&lt;li&gt;Many other add-ons to fit your needs&lt;/li&gt;
&lt;li&gt;Excellent &lt;a href="https://docs.infura.io/infura"&gt;documentation&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Use Cases&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Depending on the type of project you are building, there are several different technologies you could connect to a Node Provider. &lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Truffle / Hardhat&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;If you are writing smart contracts that interact with historical data, then a development suite such as Truffle or Hardhat would fit your needs. They both have an assortment of built-in tools that make the entire development lifecycle for your dApp much easier. Connecting to an Archive Node, in this case, is as easy as setting your provided API URL endpoint as a variable to be used in your frontend code.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Ganache&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;If you need quick access to an Archive Node for local development or testing, Truffle offers a personal blockchain that accomplishes this nicely. This blockchain is called &lt;a href="https://trufflesuite.com/docs/ganache/index.html"&gt;Ganache&lt;/a&gt;. As of &lt;a href="https://blog.infura.io/fork-ethereum-replay-historical-transactions-with-ganache-7-archive-support/"&gt;Ganache version 7.0&lt;/a&gt;, spinning up a local instance of the Ethereum blockchain with Archive access is as simple as one command:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;You could then interact with it similarly as above, using the URL: &lt;a href="http://localhost:8545"&gt;http://localhost:8545&lt;/a&gt;, or whatever you set the port to.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Direct Integration&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;If you don’t require a suite of blockchain tools, then you can use your Node Provider URL directly in your frontend code and connect to it with a JavaScript library such as ethers.js or web3.js. This is the option we will explore in the project below.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;The Project&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;As mentioned at the start of this article, we will be making a simple “Year in Review” type app to display some wallet statistics from 2021. We will clone a pre-built frontend, so all we have to worry about is querying an archive node and then displaying the data nicely.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What we will learn:&lt;/strong&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How to get an Infura API URL with archive access&lt;/li&gt;
&lt;li&gt;How to gather archive data using an Infura API URL and web3.js&lt;/li&gt;
&lt;li&gt;The JavaScript required to collect the data from the blockchain&lt;/li&gt;
&lt;li&gt;How to put the data together to display it nicely in the app&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What is needed to complete the project:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://infura.io/"&gt;An Infura account&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://git-scm.com/downloads"&gt;Git&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nodejs.org/en/"&gt;Node / npm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://code.visualstudio.com/"&gt;A code editor&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Additional resources&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.infura.io/infura"&gt;Infura docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://web3js.readthedocs.io/en/v1.7.0/web3.html"&gt;Web3.js docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;The Infura API URL&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;The first step in our project is to set up our Infura account and acquire our API Endpoint URL. Head to&lt;a href="https://infura.io/"&gt; https://infura.io/&lt;/a&gt; and either create a new account or log in.&lt;/p&gt;

&lt;p&gt;Create a new project to get the API Endpoint URL we will need later in our project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GBwTZ9uj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1vy5tl45iow2g088vzup.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GBwTZ9uj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1vy5tl45iow2g088vzup.jpg" alt="The Infura project dashboard where we get the Infura RPC endpoint URL" width="880" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since archive access is now free for all users, we don’t need to complete any other steps with our Infura account.&lt;/p&gt;

&lt;p&gt;With that out of the way, let’s start working on the frontend!&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;The Frontend&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;We will be building on top of a pre-made React frontend for the rest of this project. If you’ve never used React before, that’s okay. We will be walking through the rest of the steps together. &lt;/p&gt;

&lt;p&gt;To install the project properly, we will use &lt;strong&gt;git&lt;/strong&gt; and &lt;strong&gt;node package manager&lt;/strong&gt; (npm). To see if they are already installed, we can check the version numbers in the command line:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;





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

&lt;/div&gt;



&lt;p&gt;If they still need to be installed on your machine, you can get them at the following links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Node / npm&lt;/strong&gt;: &lt;a href="https://nodejs.org/en/"&gt;https://nodejs.org/en/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Git&lt;/strong&gt;: &lt;a href="https://git-scm.com/downloads"&gt;https://git-scm.com/downloads&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once installed, we are ready to start working on the rest of the project:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In the command line, navigate to the folder you would like to work out of and clone the repository for our project:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; git clone https://github.com/paul-mcaviney/archive-node-project-frontend.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Change directories into the new project folder and install the required dependencies:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd archive-node-project-frontend
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;After the dependencies finish installing, let’s run the project to make sure it’s working correctly so far:
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;/div&gt;



&lt;p&gt;If everything is installed correctly, we will now have a frontend running on &lt;strong&gt;&lt;a href="http://localhost:3000"&gt;http://localhost:3000&lt;/a&gt;&lt;/strong&gt; that looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--D1EAK0E---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/samql69o0j6usqvgxj4v.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--D1EAK0E---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/samql69o0j6usqvgxj4v.jpg" alt="Our React project frontend. A user enters in a wallet address to receive stats from 2021" width="880" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There’s a text field we will use to enter a wallet address. Clicking the Submit button takes us to our results page. We can also return to the input page from here by pressing the &lt;strong&gt;Enter New Address&lt;/strong&gt; button.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Before we start coding, we need to install one more dependency. We will be using &lt;strong&gt;web3.js&lt;/strong&gt; to access an Archive Node with our Infura URL. To install web3.js, type the following command in the directory for our project:
&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 web3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;We will do all of our coding in the &lt;strong&gt;App.js&lt;/strong&gt; file under the &lt;strong&gt;src&lt;/strong&gt; folder. The first bit of code we need to write is to import web3 to our project and connect it to our Infura URL. Under the import statements, and before the &lt;strong&gt;App&lt;/strong&gt; function, add the following code:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Web3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;web3&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;infuraURL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;YOUR_INFURA_URL_HERE&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;web3&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;Web3&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;Web3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;HttpProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;infuraURL&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;Note&lt;/strong&gt;: Do not upload this project to a public repository without first hiding your actual Infura URL. You can use environment variables for this.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We’ll be using the &lt;strong&gt;useState&lt;/strong&gt; React hook to update our UI. You’ll notice it’s already imported at the top of our file. Next, let’s add some React state variables to make it easier to display the data we gather from our Archive Node. Under the &lt;strong&gt;results&lt;/strong&gt; state variable, add the following:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&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;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setAddress&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="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;currentBalance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCurrentBalance&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="mi"&gt;0&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;startOfYearBalance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setStartOfYearBalance&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="mi"&gt;0&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;endOfYearBalance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setEndOfYearBalance&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="mi"&gt;0&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;balanceDifference&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setBalanceDifference&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="mi"&gt;0&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;transactionCount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setTransactionCount&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="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Now we need to update the &lt;strong&gt;handleInput&lt;/strong&gt; function to assign the user input to our address state variable instead of logging the comment:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleInput&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="nx"&gt;setAddress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&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="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: You’ll notice we didn’t put any checks here to make sure what the user inputs is actually an Ethereum wallet address. This is for the sake of keeping this tutorial simple. You will want to handle this differently if deploying publicly.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The last bit of JavaScript is an asynchronous function that will gather the data from the Archive Node, convert it to more readable values, and set our state variables. Under the comment that says &lt;em&gt;Your JavaScript code will go here&lt;/em&gt;, type the following code:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Access and process data from Ethereum blockchain&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;accessEthereum&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;// 2021 Start and End Block variables &lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;START_2021_BLOCK&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;11565019&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;END_2021_BLOCK&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;13916165&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Get current balance of address &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;web3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;eth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getBalance&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;// Convert balance from wei to ETH and set state variable&lt;/span&gt;
    &lt;span class="nx"&gt;setCurrentBalance&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;web3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;utils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fromWei&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;toString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ether&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="c1"&gt;// Get wallet balance at the start of 2021 (Block #11565019)&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;startBalance&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;web3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;eth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getBalance&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;START_2021_BLOCK&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Get wallet balance at the end of 2021 (Block #13916165)&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;endBalance&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;web3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;eth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getBalance&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;END_2021_BLOCK&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Convert startBalance to ETH and set state variable&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;startBalanceAsETH&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;web3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;utils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fromWei&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;startBalance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ether&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;setStartOfYearBalance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;startBalanceAsETH&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Convert endBalance to ETH and set state variable&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;endBalanceAsETH&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;web3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;utils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fromWei&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;endBalance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ether&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;setEndOfYearBalance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;endBalanceAsETH&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Set balanceDifference from start to end of 2021&lt;/span&gt;
    &lt;span class="nx"&gt;setBalanceDifference&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;endBalanceAsETH&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;startBalanceAsETH&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Get transaction count at start of 2021 (Block #11565019)&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;startTransactions&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;web3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;eth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getTransactionCount&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;START_2021_BLOCK&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Get transaction count at end of 2021 (Block #13916165)&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;endTransactions&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;web3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;eth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getTransactionCount&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;END_2021_BLOCK&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Set total transaction count in 2021&lt;/span&gt;
    &lt;span class="nx"&gt;setTransactionCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;endTransactions&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;startTransactions&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Received results, condition met to show them on screen&lt;/span&gt;
    &lt;span class="nx"&gt;setResults&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Moving on to the HTML, the first thing we need to do is replace the button function with the new one we just wrote. Change the function call for the button under the &lt;em&gt;Change this button function&lt;/em&gt; comment:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;onClick=&lt;/span&gt;&lt;span class="s"&gt;{accessEthereum}&lt;/span&gt; &lt;span class="na"&gt;className=&lt;/span&gt;&lt;span class="s"&gt;'form-button'&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;'submit'&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;'submit'&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;'submit'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;The final bit of code we need is the HTML that will display the data we gathered from our Archive Node. In the &lt;strong&gt;return&lt;/strong&gt; statement, scroll down to the comment that says &lt;em&gt;Your HTML code will go here&lt;/em&gt; and add the following:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;h3&amp;gt;&lt;/span&gt;{address}&lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;className=&lt;/span&gt;&lt;span class="s"&gt;'result-heading'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Current Balance&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;{currentBalance} ETH&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;className=&lt;/span&gt;&lt;span class="s"&gt;'result-heading'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Start of 2021 Balance&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;{startOfYearBalance} ETH&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;className=&lt;/span&gt;&lt;span class="s"&gt;'result-heading'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;End of 2021 Balance&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;{endOfYearBalance} ETH&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;className=&lt;/span&gt;&lt;span class="s"&gt;'result-heading'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Difference from Start of 2021&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;{balanceDifference} ETH&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;className=&lt;/span&gt;&lt;span class="s"&gt;'result-heading'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Number of transactions in 2021&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;{transactionCount}&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;br&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To see the complete project code, check out this &lt;a href="https://github.com/paul-mcaviney/archive-node-project-complete"&gt;Github repository&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now let’s test out our app and see if it works! First, start the app:
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;/div&gt;



&lt;p&gt;Enter an Ethereum wallet address to the text field and hit &lt;strong&gt;Submit&lt;/strong&gt;. If you don’t have a wallet address that was active in 2021, you can use &lt;a href="https://twitter.com/VitalikButerin"&gt;Vitalik’s.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KlW334FL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kl4tr6fm1t2rbu1rg20x.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KlW334FL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kl4tr6fm1t2rbu1rg20x.jpg" alt="The results from querying an archive node for data about wallet transactions in 2021" width="880" height="1012"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Awesome! Our results are displayed correctly, and we can see all the activity of the wallet address in 2021!&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;By following this tutorial, you accessed the data on an Archive Node using your Infura API Endpoint URL, then displayed it nicely in a simple &lt;em&gt;ETH Year in Review&lt;/em&gt; app.&lt;/p&gt;

&lt;p&gt;An Archive Node is required to access data from the Ethereum Blockchain prior to the most recent 128 blocks. They store all historical state data from the very first block and serve it up much more quickly and efficiently than a Full Node. Now that Infura offers free Archive Node access to all users, gathering historical blockchain data has never been easier!&lt;/p&gt;

</description>
      <category>web3</category>
      <category>ethereum</category>
      <category>blockchain</category>
      <category>infura</category>
    </item>
    <item>
      <title>How To Mint an NFT on Polygon</title>
      <dc:creator>Paul McAviney</dc:creator>
      <pubDate>Tue, 10 May 2022 22:32:28 +0000</pubDate>
      <link>https://forem.com/0xpaulie/how-to-mint-an-nft-on-polygon-kg</link>
      <guid>https://forem.com/0xpaulie/how-to-mint-an-nft-on-polygon-kg</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Non-Fungible Tokens (NFTs) have exploded in popularity over the last year. And with NFTs being used for &lt;a href="https://opensea.io/" rel="noopener noreferrer"&gt;art&lt;/a&gt;, &lt;a href="https://boredapeyachtclub.com/" rel="noopener noreferrer"&gt;PFPs&lt;/a&gt;, lifestyle brands, sports, games, &lt;a href="https://pages.consensys.net/nfts-the-metaverse-ready-for-take-off" rel="noopener noreferrer"&gt;the metaverse&lt;/a&gt;, and more, they won’t be going away anytime soon. But the current state of NFTs has a few problems - notably, minting on Ethereum can be prohibitively expensive and the metadata behind those NFTs is often centralized.  &lt;/p&gt;

&lt;p&gt;In this article, we’ll look at one way to solve those issues by creating and deploying an NFT to the Polygon Network and using IPFS to store the metadata. In our example, we’ll use &lt;a href="https://trufflesuite.com/" rel="noopener noreferrer"&gt;Truffle&lt;/a&gt; as our development environment and &lt;a href="https://infura.io/" rel="noopener noreferrer"&gt;Infura&lt;/a&gt; to connect and interact with the blockchain and IPFS. &lt;/p&gt;

&lt;h3&gt;
  
  
  A Quick Overview of NFTs
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Fungible&lt;/strong&gt; tokens are cryptographic tokens that can be exchanged for any other of the same token (1 == 1). These include cryptocurrencies such as Bitcoin (BTC) or ETH. One Bitcoin is exactly the same as any other Bitcoin.&lt;/p&gt;

&lt;p&gt;In contrast, &lt;strong&gt;&lt;a href="https://consensys.net/knowledge-base/a-blockchain-glossary-for-beginners/#NFT" rel="noopener noreferrer"&gt;NFTs&lt;/a&gt;&lt;/strong&gt; are &lt;em&gt;&lt;strong&gt;not&lt;/strong&gt; fungible&lt;/em&gt; - one token is &lt;strong&gt;not&lt;/strong&gt; replaceable by another, and they may have varying values (1 != 1). An NFT is an undisputable representation of digital ownership. It can be used to represent any manner of digital property such as images, videos, music, and so much more. &lt;/p&gt;

&lt;h3&gt;
  
  
  NFTs on Ethereum and Layer Two
&lt;/h3&gt;

&lt;p&gt;Most NFTs are created on the &lt;a href="https://ethereum.org/en/" rel="noopener noreferrer"&gt;Ethereum Network&lt;/a&gt;, as it allows for the greatest sense of security and decentralization. However, for the average person, there is a major issue: Transacting on Layer 1 of the Ethereum Network is expensive. &lt;/p&gt;

&lt;p&gt;Over the course of 2021, several solutions to this problem have gained popularity. Layer 2 solutions such as &lt;a href="https://arbitrum.io/" rel="noopener noreferrer"&gt;Arbitrum&lt;/a&gt;, &lt;a href="https://zksync.io/userdocs/" rel="noopener noreferrer"&gt;zkSync&lt;/a&gt;, and the &lt;a href="https://polygon.technology/" rel="noopener noreferrer"&gt;Polygon Network&lt;/a&gt; are here to provide a more user-friendly experience. Transaction fees on these networks are a fraction of what they would be on Layer 1, and in most cases, significantly faster.&lt;/p&gt;

&lt;p&gt;Another current problem with NFTs is that the metadata they contain isn’t always stored in a decentralized manner. If the organization hosting the metadata disappears, so does the value of your NFT. The best solution is to host the metadata using a global, peer-to-peer file system such as InterPlanetary File Storage (IPFS).&lt;/p&gt;

&lt;p&gt;Combining technologies such as Polygon and IPFS creates a cost-effective method to deploy and store your NFT in a more decentralized and permanent way. Although we could use no-code services such as those provided by &lt;a href="https://consensys.net/solutions/nft-experiences/" rel="noopener noreferrer"&gt;ConsenSys&lt;/a&gt;, it’s more fun to actually deploy one yourself and you will get a better understanding of how it all works behind the scenes. &lt;/p&gt;

&lt;p&gt;So let’s look at how you can create and deploy an NFT to the Polygon Network. We will use Truffle as our development environment and Infura to connect and interact with the blockchain, and to store the metadata with IPFS. &lt;/p&gt;

&lt;p&gt;Before deploying, we will test on a local instance of a blockchain with Ganache. When it’s ready to go live, we will deploy to the Polygon Mumbai Test Network and will verify the NFT on OpenSea, the world’s most popular NFT platform.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Project
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What You Will Learn
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Upload the NFT image and metadata to IPFS via Infura&lt;/li&gt;
&lt;li&gt;Set up the Polygon Network in MetaMask and get test funds&lt;/li&gt;
&lt;li&gt;Set up Truffle Development Environment&lt;/li&gt;
&lt;li&gt;Write an NFT smart contract&lt;/li&gt;
&lt;li&gt;Test deployment locally using Ganache&lt;/li&gt;
&lt;li&gt;Deploy to Polygon testnet using Truffle console and Infura&lt;/li&gt;
&lt;li&gt;Verify the NFT on opensea.io&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What You Will Need
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.npmjs.com/cli/v8/configuring-npm/install" rel="noopener noreferrer"&gt;NodeJS / NPM&lt;/a&gt; - installation and package management&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://trufflesuite.com/docs/truffle/getting-started/installation/" rel="noopener noreferrer"&gt;Truffle&lt;/a&gt; - development environment&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://trufflesuite.com/docs/ganache/quickstart/" rel="noopener noreferrer"&gt;Ganache&lt;/a&gt; - local blockchain instance for testing&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://infura.io/" rel="noopener noreferrer"&gt;Infura account&lt;/a&gt; - used to interact with IPFS and Polygon Networks&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://metamask.io/" rel="noopener noreferrer"&gt;MetaMask account&lt;/a&gt; - supply funds to process transactions&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Additional Resources
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.polygon.technology/docs/develop/getting-started" rel="noopener noreferrer"&gt;Polygon Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://trufflesuite.com/docs/truffle/" rel="noopener noreferrer"&gt;Truffle Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://infura.io/docs/ethereum" rel="noopener noreferrer"&gt;Infura Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.metamask.io/guide/" rel="noopener noreferrer"&gt;MetaMask Docs&lt;/a&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fphy17jxcnaf4u4qk8862.jpg" 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%2Fphy17jxcnaf4u4qk8862.jpg" alt="An image saying "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up Accounts
&lt;/h2&gt;

&lt;p&gt;Before we get to the fun parts like building and testing, let’s set up our accounts and get everything in place. This will ensure the rest of the process goes smoothly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Get an Infura Account
&lt;/h3&gt;

&lt;p&gt;Infura is an Ethereum node provider and API. It will allow us to easily connect to the Polygon Network and also provides an easy-to-use method for utilizing IPFS.&lt;/p&gt;

&lt;p&gt;The first thing we need to do is head to &lt;a href="https://infura.io/register" rel="noopener noreferrer"&gt;infura.io&lt;/a&gt; and set up a free account. After verifying our email address, we can access the dashboard, where we can make new projects. The Polygon Network isn’t enabled by default, however.&lt;/p&gt;

&lt;p&gt;We can add Polygon to our plan by selecting the “Add-Ons” tab on the left-hand side of the screen and scrolling down to “Network Add-Ons”. Next, we select “Polygon PoS Add-On” and go through the prompt to add it. &lt;/p&gt;

&lt;p&gt;Now we’re ready to create a new project. Let’s head back to the dashboard and click on the “Create New Project” button. We’ll select Ethereum as the product and name our project &lt;strong&gt;Polygon-NFT&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Once our project is created, there are several things to note:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Project ID&lt;/li&gt;
&lt;li&gt;The project secret&lt;/li&gt;
&lt;li&gt;Endpoints selection&lt;/li&gt;
&lt;li&gt;Our endpoint link&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s change our Endpoint from &lt;code&gt;MAINNET&lt;/code&gt; to &lt;code&gt;POLYGON MUMBAI&lt;/code&gt;, which is the Polygon  testnet. Our Endpoint link will then change. We will need the values on this page later, but for now, we are done with the project page.&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%2Fw7aoov6t0xl9kcwkbnaz.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%2Fw7aoov6t0xl9kcwkbnaz.png" alt="A view of our Infura project, with the endpoint switched from mainnet to polygon mumbai"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  IPFS via Infura
&lt;/h3&gt;

&lt;p&gt;Since we are already in our Infura account, let’s go ahead and create another project. This one will be for utilizing IPFS to store the image and metadata of our NFT. This time when we create a new project, we will select IPFS as the product. Let’s name this one &lt;strong&gt;Polygon-NFT-Metadata&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For the next steps we will need the Project ID, project secret, and endpoint URL, but first, we need an image for our NFT.&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%2Fcdo23fldtgfbmxrarw0c.jpg" 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%2Fcdo23fldtgfbmxrarw0c.jpg" alt="he image to be used for our Polygon NFT -- It's dark navy blue with the words "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Just right-click and save this to your machine ;)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Feel free to use your own image moving forward. OpenSea recommends the image size to be 350 x 350 pixels.&lt;/p&gt;

&lt;p&gt;Now let’s upload the image to IPFS!&lt;/p&gt;

&lt;p&gt;Using a command terminal, we will &lt;code&gt;cd&lt;/code&gt; into the folder where our image is stored.&lt;/p&gt;

&lt;p&gt;To upload the image, type 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;curl -X POST -F file=@myfile \ -u "PROJECT_ID:PROJECT_SECRET" \ "https://ipfs.infura.io:5001/api/v0/add"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;span&gt;Note:&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;@myfile&lt;/code&gt; should be the name of the image file in the current folder. So in our case &lt;code&gt;@polygon-nft.jpg&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;PROJECT_ID&lt;/code&gt; and &lt;code&gt;PROJECT_SECRET&lt;/code&gt; will be the keys provided in the settings for our Infura project.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The output from the command should look 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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F27wxccnkb8ec5pfjj0zk.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%2F27wxccnkb8ec5pfjj0zk.png" alt="The console readout after uploading an image to IPFS via the command line"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The most important part of the output will be our “Hash”. We can actually verify the image was uploaded successfully by pasting that Hash into the following URL: &lt;a href="https://ipfs.io/ipfs/YOUR_HASH_HERE" rel="noopener noreferrer"&gt;https://ipfs.io/ipfs/YOUR_HASH_HERE&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It’s important to note that Infura pins our data to IPFS by default. If we ever want to remove an item from IPFS we have to &lt;a href="https://infura.io/docs/ipfs#section/Getting-Started/Unpin-a-file" rel="noopener noreferrer"&gt;unpin it&lt;/a&gt;. Now that our image is stored on IPFS, let’s get the metadata stored there as well. According to &lt;a href="https://docs.opensea.io/docs/metadata-standards" rel="noopener noreferrer"&gt;standards by OpenSea&lt;/a&gt;, we will want our metadata in JSON format like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{ 
  "name": "My Sweet Polygon NFT",   
  "description": "Our amazing NFT deployed to the Polygon Network",     
  "image": "ipfs://YOUR_HASH_HERE" 
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So let’s create a new text file in the same folder on our local machine as our NFT image. We can use any text editor for this; it doesn’t need to be anything fancy.&lt;/p&gt;

&lt;p&gt;We’ll add the metadata in the same format as above. However, rather than using &lt;code&gt;YOUR_HASH_HERE&lt;/code&gt; we’ll insert the actual Hash for our image that we just verified. We’ll save the file as &lt;code&gt;nft-metadata.json&lt;/code&gt;. We also need to make sure there is no comma after the last item in our JSON file. If there is a comma, then OpenSea will not display the NFT properly. &lt;/p&gt;

&lt;p&gt;Now we can add this file to IPFS using the same command as last time; we just need to replace the file name with &lt;code&gt;@nft-metadata.j&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Excellent! We now have our metadata pinned to IPFS which has a link that points to our already pinned image. We’ll copy the Hash in the output to use later.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting Up MetaMask
&lt;/h3&gt;

&lt;p&gt;In order to interact with the Polygon Network and to pay any transaction fees, we will need to set up a Web3 wallet. We will use MetaMask to do this. It is installed as a browser extension and allows us to connect to Decentralized Apps (dApps). &lt;/p&gt;

&lt;p&gt;Let’s head over to &lt;a href="https://metamask.io/" rel="noopener noreferrer"&gt;metamask.io&lt;/a&gt; and download the extension for our browser. When using a crypto wallet like MetaMask, it’s a good idea to understand &lt;a href="https://metamask.zendesk.com/hc/en-us/articles/360015489591-Basic-Safety-and-Security-Tips-for-Metamask" rel="noopener noreferrer"&gt;wallet safety&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;span&gt;Remember&lt;/span&gt;:&lt;/strong&gt; Never share your seed phrase with &lt;strong&gt;anyone&lt;/strong&gt;! Whoever has your seed phrase can withdraw your tokens.&lt;/p&gt;

&lt;p&gt;We will need to use the 12-word seed phrase when setting up our Truffle project. So be sure to write that down and save it for later. Once we install MetaMask and open it to the dashboard, we need to add Polygon to our Networks dropdown.&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%2Fq920i3hflbwczvym5eq9.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%2Fq920i3hflbwczvym5eq9.png" alt="Where to click to add new networks to metamask"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When we click the dropdown, it reveals a button to add new networks to the list. So we’ll press the “Add Network” button, and &lt;a href="https://docs.polygon.technology/docs/develop/metamask/config-polygon-on-metamask/" rel="noopener noreferrer"&gt;add both the Polygon Mainnet and Mumbai Testnet&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;We will need to enter in the following information:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mumbai Testnet&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Network Name: Mumbai (Polygon Testnet)&lt;/li&gt;
&lt;li&gt;New RPC URL: &lt;a href="https://rpc-mumbai.maticvigil.com/" rel="noopener noreferrer"&gt;https://rpc-mumbai.maticvigil.com/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Chain ID: 80001&lt;/li&gt;
&lt;li&gt;Currency Symbol: MATIC&lt;/li&gt;
&lt;li&gt;Block Explorer URL:&lt;a href="https://mumbai.polygonscan.com/" rel="noopener noreferrer"&gt; https://mumbai.polygonscan.com/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Polygon Mainnet&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Network Name: Polygon Mainnet&lt;/li&gt;
&lt;li&gt;New RPC URL: &lt;a href="https://polygon-rpc.com/" rel="noopener noreferrer"&gt;https://polygon-rpc.com/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Chain ID: 137&lt;/li&gt;
&lt;li&gt;Currency Symbol: MATIC&lt;/li&gt;
&lt;li&gt;Block Explorer URL:&lt;a href="https://polygonscan.com/" rel="noopener noreferrer"&gt; https://polygonscan.com/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now we have the Polygon Network added to our MetaMask, but if we switch to the Mumbai Testnet, there’s no MATIC! Let’s change that. We’ll need to copy our wallet address, which is listed under the name of our Account. It starts with 0x…&lt;/p&gt;

&lt;p&gt;Next, we’ll head over to &lt;a href="https://faucet.polygon.technology/" rel="noopener noreferrer"&gt;https://faucet.polygon.technology/&lt;/a&gt; which is a faucet that provides test funds for development. We need to select the Mumbai Network and then paste our address into the text field. Once we hit “Submit” we should see some MATIC tokens in our MetaMask wallet after a minute or two.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; If you have multiple accounts in your MetaMask wallet, Truffle uses the first one by default. So be sure to add the test MATIC tokens to the first account in your list.&lt;/p&gt;

&lt;p&gt;Now that we have loaded our wallet with some test tokens, we are ready to move on.&lt;/p&gt;

&lt;h3&gt;
  
  
  Install Truffle and Ganache
&lt;/h3&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Truffle&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Truffle is a development environment that provides tools to make building on the blockchain much easier. In order to install it via the command line, we will need NodeJS v8.9.4 or later and Node Package Manager (npm). If it’s not already installed, &lt;a href="https://nodejs.dev/learn/how-to-install-nodejs" rel="noopener noreferrer"&gt;check out this link&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Once it’s installed on our machine, we can install Truffle using this command in the terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -g truffle
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can type the command &lt;code&gt;truffle version&lt;/code&gt; afterward to ensure it was installed correctly. If there are any errors, be sure to add the npm modules to your path.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Ganache&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Next we’ll install Ganache, a local blockchain instance used for testing before deploying to the Mumbai Testnet.&lt;/p&gt;

&lt;p&gt;Ganache has a GUI version that can be downloaded &lt;a href="https://trufflesuite.com/ganache/" rel="noopener noreferrer"&gt;here&lt;/a&gt;, but we will use the terminal version for the rest of this tutorial. It can be installed using 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;npm install ganache --global
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Again, we can verify proper installation by checking the version: &lt;code&gt;ganache --version&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up Our Project
&lt;/h2&gt;

&lt;p&gt;Now that our accounts are set up and everything is installed properly, let’s start putting it all together. The first step is to navigate in our terminal to where we want to create our project and make a new directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir polygon-nft-project &amp;amp;&amp;amp; cd polygon-nft-project
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One incredibly useful thing about Truffle is they offer a full suite of “&lt;a href="https://trufflesuite.com/boxes/" rel="noopener noreferrer"&gt;boxes&lt;/a&gt;” for getting started quickly. They are essentially boilerplates that include helpful modules, pre-made smart contracts, frontend views, and more. For this project, we will utilize Truffle’s &lt;a href="https://trufflesuite.com/boxes/polygon/" rel="noopener noreferrer"&gt;Polygon Box&lt;/a&gt;. Installation is simple; we just need to type 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;truffle unbox polygon
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After installation, we can see there are several new files in our project folder. The most important ones we will be working with are the &lt;code&gt;README.md&lt;/code&gt; file, &lt;code&gt;truffle-config.polygon.js&lt;/code&gt;, the &lt;code&gt;1_deploy_simple_storage.js&lt;/code&gt; under the &lt;code&gt;migrations&lt;/code&gt; folder, and &lt;code&gt;SimpleStorage.sol&lt;/code&gt; files, which can be found in the &lt;code&gt;contracts&lt;/code&gt; folder. &lt;/p&gt;

&lt;p&gt;You will likely see an &lt;code&gt;ethereum&lt;/code&gt; and &lt;code&gt;polygon&lt;/code&gt; folder under &lt;code&gt;contracts&lt;/code&gt;. This is because typically when a project is deployed to Polygon, it should also be deployed to Ethereum so users can easily bridge their assets back and forth. We can delete the &lt;code&gt;SimpleStorage.sol&lt;/code&gt; contracts since we won’t be using them.  &lt;/p&gt;

&lt;p&gt;Taking a quick glance through the &lt;code&gt;README.md&lt;/code&gt; file, we can see that in order to deploy to the Polygon Network, we will have to add two things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The Mnemonic phrase (seed phrase) of the wallet we are using&lt;/li&gt;
&lt;li&gt;The Infura Project ID&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We’ll want to store these in a &lt;code&gt;.env&lt;/code&gt; file and make sure it’s added to our &lt;code&gt;.gitignore&lt;/code&gt; so we don’t accidentally upload these secrets if storing our project on a public repository. &lt;/p&gt;

&lt;p&gt;Downloading the Polygon Truffle Box also installed the &lt;code&gt;.dotenv&lt;/code&gt; package for us. All we need to do is create a &lt;code&gt;.env&lt;/code&gt; file in our root folder. &lt;/p&gt;

&lt;p&gt;The mnemonic phrase for our wallet can be found in our MetaMask settings under the “Security &amp;amp; Privacy” heading. The Project ID can be found under the “Keys” heading in our Infura project settings. Our &lt;code&gt;.env&lt;/code&gt; file will look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MNEMONIC="your twelve words here ..."
INFURA_PROJECT_ID="project ID # here"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next thing we should do is update Truffle to use the latest version of Solidity. In our &lt;code&gt;truffle-config.polygon.js&lt;/code&gt; file, we can add the compiler version we wish to use.&lt;/p&gt;

&lt;p&gt;Under the &lt;code&gt;compilers&lt;/code&gt; section, within the &lt;code&gt;solc&lt;/code&gt; curly braces, we’ll add the following: &lt;code&gt;version: “0.8.11”&lt;/code&gt; (the latest version of Solidity at the time of this writing).&lt;/p&gt;

&lt;p&gt;It should look like this:&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;// Configure your compilers&lt;/span&gt;
&lt;span class="nx"&gt;compilers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;solc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;version&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.8.11&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;&lt;strong&gt;Note:&lt;/strong&gt; If you didn’t delete the &lt;code&gt;SimpleStorage.sol&lt;/code&gt; contracts, then you will need to update their Solidity version in order to compile properly. Simply change the pragma line to the following: &lt;code&gt;pragma solidity &amp;gt;=0.4.21 &amp;lt;0.9.0;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The last bit of prep work is just to install the &lt;a href="https://docs.openzeppelin.com/contracts/4.x/" rel="noopener noreferrer"&gt;OpenZeppelin contract library&lt;/a&gt;, as we will import several contracts. We can install it by typing this command in the root directory of our project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install @openzeppelin/contracts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are utilizing the OpenZeppelin library to make writing our smart contract easier and much safer. The contracts we will use have had thorough security audits and it ensures we are adhering to the industry standard for NFTs.&lt;/p&gt;

&lt;p&gt;With our project set up properly, we are ready to get to the best part… Creating the NFT!&lt;/p&gt;

&lt;h3&gt;
  
  
  The Smart Contract
&lt;/h3&gt;

&lt;p&gt;We will open up our preferred code editor from our project root folder. (I’m using vscode so the command is &lt;code&gt;code .&lt;/code&gt;.) Create a new file under the &lt;code&gt;contracts&lt;/code&gt; folder named &lt;code&gt;PolygonNFT.sol&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; If you need to brush up on the Solidity coding language, check out my &lt;a href="https://blog.paulmcaviney.ca/series/solidity-basics" rel="noopener noreferrer"&gt;Solidity Basics Series&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We’ll be using the following smart contract for our NFT:&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;// SPDX-License-Identifier: MIT&lt;/span&gt;
&lt;span class="nx"&gt;pragma&lt;/span&gt; &lt;span class="nx"&gt;solidity&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="mf"&gt;0.8&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Import the OpenZeppelin contracts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@openzeppelin/contracts/token/ERC721/ERC721.sol&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@openzeppelin/contracts/utils/Counters.sol&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@openzeppelin/contracts/access/Ownable.sol&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Declare our contract and inherit from the OpenZeppelin ERC721 and Ownable contracts &lt;/span&gt;
&lt;span class="nx"&gt;contract&lt;/span&gt; &lt;span class="nx"&gt;PolygonNFT&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;ERC721&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Ownable&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Helpers for counting safely and converting data to strings&lt;/span&gt;
    &lt;span class="nx"&gt;using&lt;/span&gt; &lt;span class="nx"&gt;Counters&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;Counters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;using&lt;/span&gt; &lt;span class="nx"&gt;Strings&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;uint256&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// State variable for storing the current token Id&lt;/span&gt;
    &lt;span class="nx"&gt;Counters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Counter&lt;/span&gt; &lt;span class="kr"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;_tokenIds&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// Map token Ids to token URI&lt;/span&gt;
    &lt;span class="nf"&gt;mapping &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;uint256&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kr"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;_tokenURIs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// ERC721 requires a name for the NFT collection and a symbol&lt;/span&gt;
    &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nc"&gt;ERC721&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;PolygonNFT&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;PNFT&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="c1"&gt;// Set the URI (metadata) for tokenId&lt;/span&gt;
    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;_setTokenURI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;uint256&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;string&lt;/span&gt; &lt;span class="nx"&gt;memory&lt;/span&gt; &lt;span class="nx"&gt;_tokenURI&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nx"&gt;internal&lt;/span&gt;
        &lt;span class="nx"&gt;virtual&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;_tokenURIs&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="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;_tokenURI&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Return the Token URI - Required for viewing properly on OpenSea&lt;/span&gt;
    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;tokenURI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;uint256&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;public&lt;/span&gt;
        &lt;span class="nx"&gt;view&lt;/span&gt;
        &lt;span class="nx"&gt;virtual&lt;/span&gt;
        &lt;span class="nx"&gt;override&lt;/span&gt;
        &lt;span class="nf"&gt;returns &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="nx"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;_exists&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Token does not exist&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="nx"&gt;memory&lt;/span&gt; &lt;span class="nx"&gt;_tokenURI&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;_tokenURIs&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;_tokenURI&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Mint the NFT to the provided address, using the provided metadata URI -- only the wallet address that deployed this contract can call this function&lt;/span&gt;
    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;mint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt; &lt;span class="nx"&gt;recipient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="nx"&gt;memory&lt;/span&gt; &lt;span class="nx"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="kr"&gt;public&lt;/span&gt;
        &lt;span class="nx"&gt;onlyOwner&lt;/span&gt;
        &lt;span class="nf"&gt;returns &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;uint256&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;_tokenIds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nx"&gt;uint256&lt;/span&gt; &lt;span class="nx"&gt;newItemId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;_tokenIds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;current&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="nf"&gt;_mint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;recipient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newItemId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;_setTokenURI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newItemId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;uri&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;newItemId&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;Pretty short, right?! That’s the beautiful thing about the composability of Web3. OpenZeppelin is doing most of the heavy lifting here with their ERC721 standard.&lt;/p&gt;

&lt;p&gt;Basically, we are simply defining the NFT collection and symbol, supplying the NFT metadata via the &lt;code&gt;_setTokenURI()&lt;/code&gt; function, putting it together with our &lt;code&gt;mint()&lt;/code&gt; function, and then providing a way for OpenSea or anyone else to retrieve the NFT metadata through our &lt;code&gt;tokenURI()&lt;/code&gt; function.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing Deployment With Ganache
&lt;/h2&gt;

&lt;p&gt;Deploying to the blockchain is pretty simple, but before we can do that, we need to modify the &lt;code&gt;1_deploy_simple_storage.js&lt;/code&gt; file under the &lt;code&gt;migrations&lt;/code&gt; folder. We just need to replace every instance of &lt;code&gt;SimpleStorage&lt;/code&gt; with whatever we named our NFT smart contract. In our case: &lt;code&gt;PolygonNFT&lt;/code&gt;. We should also rename the file to &lt;code&gt;1_deploy_polygon_nft.js&lt;/code&gt; to eliminate any confusion. &lt;/p&gt;

&lt;p&gt;Our migration file should now look like this:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;PolygonNFT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;artifacts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;PolygonNFT&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;deployer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="nx"&gt;deployer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deploy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PolygonNFT&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;Before deploying our project to a live blockchain, it is common practice to test it on a local blockchain instance. We will use Ganache to do this. In a new terminal window, we will use this command to get it up and running:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;The terminal should output some Available Accounts, their Private Keys, and so on.&lt;/p&gt;

&lt;p&gt;To deploy our project to Ganache, open up the original terminal window. In the root directory of our project, type the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;truffle migrate --config=truffle-config.polygon.js --network=development
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since there are two config files in our project, we need to specify which one to use. Truffle will use the &lt;code&gt;truffle-config.js&lt;/code&gt; file by default. After hitting enter, we can see that Truffle compiles our contracts and then starts the migration. If all goes successfully, you will receive a transaction receipt that will look 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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnvmpvzbeogwnmtdmfifu.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%2Fnvmpvzbeogwnmtdmfifu.png" alt="the transaction receipt returned in the command line after a successful migration"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Take note of the contract address&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now that our contract has migrated successfully to our local blockchain instance, we can use the &lt;a href="https://trufflesuite.com/docs/truffle/getting-started/interacting-with-your-contracts.html" rel="noopener noreferrer"&gt;Truffle Console&lt;/a&gt; to interact with it. The Truffle Console is a powerful tool that allows us to use javascript to interact directly with our contract without having to set up a frontend. To use it, type the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;truffle console --config=truffle-config.polygon.js --network=development
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice how the command prompt changes to &lt;code&gt;truffle(development)&amp;gt;&lt;/code&gt;. We are now ready to start interacting with our smart contract. &lt;/p&gt;

&lt;p&gt;First, we need to get an instance of our contract. Copy the contract address from our transaction receipt to be used in this line of code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let instance = await PolygonNFT.at("YOUR_CONTRACT_ADDRESS_HERE")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will return undefined but if we type &lt;code&gt;instance&lt;/code&gt; it should output our contract ABI. Now we can call the mint function. We will need a contract address in which to send the NFT and our IPFS URI from earlier in the format: &lt;code&gt;ipfs://YOUR_HASH_HERE&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;await instance.mint("YOUR_WALLET_ADDRESS", "YOUR_METADATA_URI")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It’s important to note that the mint function is being called by the address that deployed the contract because that is the one we logged into the Truffle Console with by default. The address we placed in the code above is the recipient of the NFT.&lt;/p&gt;

&lt;p&gt;If all went well with our code above, we shouldn’t see any errors after we hit enter! We now know our contract works and we are able to mint an NFT from it. Unfortunately, since this is a local blockchain instance, we don’t have OpenSea or PolygonScan to verify that our NFT actually exists. For that, we will deploy to the Mumbai Testnet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deploy to Polygon Testnet
&lt;/h2&gt;

&lt;p&gt;The process to deploy to the Mumbai Testnet is very similar to launching on our Ganache blockchain instance. We just need to exit the Truffle console by typing &lt;code&gt;ctrl+c&lt;/code&gt; twice and then follow the exact same steps as above. The only difference is we will replace the network= &lt;code&gt;development&lt;/code&gt; with &lt;code&gt;polygon_infura_testnet&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Before moving forward, we need to make sure our &lt;code&gt;Mnemonic phrase&lt;/code&gt; and &lt;code&gt;Project ID&lt;/code&gt; are set up properly in our &lt;code&gt;.env&lt;/code&gt; file otherwise, the next steps won’t work. (See the steps in the Setting Up Our Project section.) With those in place, our commands will now look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;truffle migrate --config=truffle-config.polygon.js --network=polygon_infura_testnet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The migration will take a little bit longer than our Ganache instance. Once it’s complete it will output a transaction receipt that looks similar to our last one. This time we can verify that our contract was successfully migrated to the Mumbai Testnet by entering our contract address to &lt;a href="https://mumbai.polygonscan.com/address/" rel="noopener noreferrer"&gt;https://mumbai.polygonscan.com/&lt;/a&gt;address/YOUR_ADDRESS_HERE&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%2Fk0pnac4gzj5lg7u1agei.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%2Fk0pnac4gzj5lg7u1agei.png" alt="what the transaction looks like on Polygonscan"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Excellent! Our contract is live on the Mumbai Testnet! Now let’s interact with it and actually mint our NFT!&lt;/p&gt;

&lt;p&gt;We’ll access the Truffle Console using the same commands as before, again, replacing the network= &lt;code&gt;development&lt;/code&gt; with &lt;code&gt;polygon_infura_testnet&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;truffle console --config=truffle-config-polygon.js --network=polygon_infura_testnet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Get an instance of our contract using the contract address that was output on our Mumbai Testnet transaction receipt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let instance = await PolygonNFT.at("YOUR_CONTRACT_ADDRESS_HERE")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now, for the moment we’ve been building towards this entire article! Mint our NFT to our desired address using our IPFS URI in the format: &lt;code&gt;ipfs://YOUR_HASH_HERE&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;await instance.mint("YOUR_WALLET_ADDRESS", "YOUR_METADATA_URI")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If there aren't any errors, we can check our contract on &lt;code&gt;mumbai.polygonscan&lt;/code&gt; again and see that our &lt;code&gt;mint()&lt;/code&gt; function was called! This time, we can verify that our NFT actually exists by checking it out on OpenSea.&lt;/p&gt;

&lt;h2&gt;
  
  
  Verify Our NFT On OpenSea
&lt;/h2&gt;

&lt;p&gt;We can easily check out our new NFT on OpenSea by copying our contract address into the search bar at &lt;a href="https://testnets.opensea.io/" rel="noopener noreferrer"&gt;https://testnets.opensea.io/&lt;/a&gt;. Ethereum addresses have &lt;a href="https://support.mycrypto.com/general-knowledge/ethereum-blockchain/ethereum-address-has-uppercase-and-lowercase-letters/" rel="noopener noreferrer"&gt;two versions&lt;/a&gt;, one that is &lt;em&gt;checksummed&lt;/em&gt; and one that is not. The difference being the non-checksummed version is all lowercase. We may need to use the non-checksummed version to find our NFT on OpenSea. We can get this address by clicking on the Txn Hash on &lt;code&gt;mumbai.polygonscan&lt;/code&gt; and then copying the address across from &lt;code&gt;Interacted With (To):&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%2Fobu89gwof9iafifrkkcs.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%2Fobu89gwof9iafifrkkcs.png" alt="The highlighted address"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Your contract address will be different&lt;/p&gt;

&lt;p&gt;If our metadata was entered correctly we should now see our beautiful, new NFT live on OpenSea!&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%2Fkfyyseatajpba08dmi2v.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%2Fkfyyseatajpba08dmi2v.png" alt="our beautiful new NFT as seen on OpenSea"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Congratulations! You have successfully deployed an NFT to the Polygon Mumbai Testnet! You uploaded your NFT image and metadata to IPFS using Infura’s API, set up your Truffle project and wrote a smart contract to create an NFT, tested deployment locally using Ganache, deployed to the Polygon Testnet with Truffle, Infura, and MetaMask, and finally, verified your NFT on OpenSea.&lt;/p&gt;

&lt;p&gt;You now have the knowledge to deploy to the Polygon Mainnet, just make sure you have real MATIC tokens in your MetaMask wallet. Additionally, when deploying, be sure to use network=&lt;code&gt;polygon_infura_mainnet&lt;/code&gt; instead of &lt;code&gt;polygon_infura_testnet&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Your next steps would be to deploy to the Ethereum Mainnet to be able to bridge your NFT from Layer 2 to Layer 1. That is the topic for another article so be sure to check out the &lt;a href="https://docs.polygon.technology/docs/develop/ethereum-polygon/getting-started" rel="noopener noreferrer"&gt;Polygon Docs&lt;/a&gt; in the meantime.&lt;/p&gt;

&lt;p&gt;Thank you for following along with this tutorial! Take care, and happy building!&lt;/p&gt;

&lt;p&gt;(The code for this project can be found here: &lt;a href="https://github.com/paul-mcaviney/polygon-nft-project" rel="noopener noreferrer"&gt;https://github.com/paul-mcaviney/polygon-nft-project&lt;/a&gt;)&lt;/p&gt;

</description>
      <category>nft</category>
      <category>polygon</category>
      <category>truffle</category>
      <category>infura</category>
    </item>
  </channel>
</rss>
