<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>Explorer of things</title>
        <link>https://paragraph.com/@harrywang</link>
        <description>I am a software engineer enthusiastic about challenging things.</description>
        <lastBuildDate>Sat, 02 May 2026 00:01:35 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <copyright>All rights reserved</copyright>
        <item>
            <title><![CDATA[First Bite of Web3]]></title>
            <link>https://paragraph.com/@harrywang/first-bite-of-web3</link>
            <guid>gnT471maDKRsnsog7zLl</guid>
            <pubDate>Mon, 03 Jan 2022 08:00:41 GMT</pubDate>
            <description><![CDATA[IntroductionWhat is Web3? It means different things for different people. Even the Ethereum co-founder Gavin Wood, who coined this term in 2014 can’t give an exact definition of Web3. Loosely speaking, Web3 is an idea for a new iteration of the World Wide Web that incorporates decentralization based on blockchains. Web1.0 refers roughly to the period from 1991 to 2004, where most websites were static webpages, and the vast majority of users were consumers, not producers, of content. Since 200...]]></description>
            <content:encoded><![CDATA[<h2 id="h-introduction" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Introduction</h2><p>What is Web3? It means different things for different people. Even the Ethereum co-founder Gavin Wood, who coined this term in 2014 can’t give an exact definition of Web3. Loosely speaking, Web3 is an idea for a new iteration of the World Wide Web that incorporates decentralization based on blockchains.</p><p>Web1.0 refers roughly to the period from 1991 to 2004, where most websites were static webpages, and the vast majority of users were consumers, not producers, of content.</p><p>Since 2004, internet had evolved to the Web 2.0 phase, when the internet centered on the idea of “the web as platform“ , and user-created content dominated social-networking services, blogs, among other services. Web 2.0 is still considered the dominant form of internet as of today.</p><p>Specific visions for Web3 differ, but they revolve around the idea of decentralization, and often incorporate blockchain technologies, such as various cryptocurrencies and non-fungible tokens (NFTs). In recent years, decentralized finance (DeFi), and decentralized autonomous organizations (DAOs) are critical propellent of the Web3 movement.</p><h2 id="h-overview" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Overview</h2><p>This article is not trying to go down the rabbit hole and explain what exactly Web3 is. This article serves as an amuse-bouche for your formal Web3 dinner, and opens the Web3 world to you.</p><p>This article gives a step by step guide to develop a very simple Web3 application, which displays the Ethereum (ETH) balance of your ETH wallet, using <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://web3js.readthedocs.io/en/v1.5.2/">web3.js</a>.</p><h2 id="h-step-by-step-guide" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Step by Step Guide</h2><h3 id="h-setup-metamask" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Setup Metamask</h3><p>This application is using <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://metamask.io/">Metamask</a> to interact with the Ethereum blockchain. If you are new to Metamask, follow <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://metamask.io/download.html">this page</a> and install Metamask for Chrome.</p><p>After installing Metamask and creating an account, sign in to your account.</p><p>Since this application is mainly for demo purpose, we are gonna use the Rinkeby Test Network for development, rather than Ethereum Mainnet (any operation on the Mainnet costs real money). After you sign into Metamask, toggle the Networks menu on top of Metamask and choose Rinkeby Test Network as shown in the following screenshot:</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/e06495ad1220884a001990245f9ed444a006ca626bd9ef95ffd1f62270af53cf.png" alt="Choose Rinkeby Test Network" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Choose Rinkeby Test Network</figcaption></figure><h3 id="h-deposit-test-eth" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Deposit test ETH</h3><p>After the ETH account is created in Metamask, the default test ETH balance for the Rinkeby Test Network is 0. In order to show non zero balance in our application, we need to find a way to deposit some test ETH into our wallet.</p><p>We can use <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://faucets.chain.link/rinkeby">Chainlink Faucets</a> to deposit test ETH into your ETH account in Metamask as shown in the following screenshot:</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/a456f62793fed7be6a064dc59b9580a4697c68fc42ceed3a934a751cc87a6aa0.png" alt="Deposit Test ETH" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Deposit Test ETH</figcaption></figure><p>In the Network section, choose Ethereum Rinkeby, and in the Testnet account address, paste the Metamask account address that you just copy to clipboard as shown in the following screenshot:</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/dd18d642a6b41ee97c2d2c01a34f127079f0374db0aa3c4a5ac61083b15eed08.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>So far you can only add 0.1 ETH to your test account per request. If you want to add more than 0.1 ETH to your test account, you could request multiple times.</p><p>By now, you already have a working ETH account with some test ETH on MetaMask. We are ready to move on to the fun part.</p><h3 id="h-install-homebrew-and-node" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Install Homebrew and Node</h3><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://brew.sh/">Homebrew</a> is a free and open-source software package management system that simplifies the installation of software on Apple&apos;s operating system, macOS, as well as Linux. In this application, we are gonna use Homebrew to install the required libraries for our application. Assuming that you are using MacOS or Linux system for this application, paste the following in a macOS Terminal or Linux shell prompt:</p><pre data-type="codeBlock" text="/bin/bash -c &quot;$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)&quot;
"><code><span class="hljs-operator">/</span>bin<span class="hljs-operator">/</span>bash <span class="hljs-operator">-</span>c <span class="hljs-string">"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"</span>
</code></pre><p>We are going to use <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.npmjs.com/about-npm">npm</a> to manage the packages required for our application. Installing <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://nodejs.org/en/about/">Node.js</a> comes with npm, which we later use to install the required packages. Run the following command:</p><pre data-type="codeBlock" text="brew install node
"><code></code></pre><h3 id="h-create-web-application-skeleton" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Create Web Application Skeleton</h3><p>There are a couple of ways to create a web application skeleton. Some popular choices are <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://create-react-app.dev/">create-react-app</a> and <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://nextjs.org/">next.js</a>. In this application, we are going to use next.js to create the skeleton of the web application. In your desired directory, run the following command:</p><pre data-type="codeBlock" text="npx create-next-app web3-demo --use-npm --example &quot;https://github.com/vercel/next-learn/tree/master/basics/learn-starter&quot;
"><code>npx create<span class="hljs-operator">-</span>next<span class="hljs-operator">-</span>app web3<span class="hljs-operator">-</span>demo <span class="hljs-operator">-</span><span class="hljs-operator">-</span>use<span class="hljs-operator">-</span>npm <span class="hljs-operator">-</span><span class="hljs-operator">-</span>example <span class="hljs-string">"https://github.com/vercel/next-learn/tree/master/basics/learn-starter"</span>
</code></pre><p>Under the hood, this uses the tool called <code>create-next-app</code> , which boostraps a Next.js app for you. It uses <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/vercel/next-learn/tree/master/basics/learn-starter">this template</a> through the <code>--example</code> flag.</p><p>Don’t be intimidated by the new <code>npx</code> command. You can think of npx as an alternative to npm. While they are performing the similar function, npx helps you to avoid npm dependencies and versioning. In most cases, npx is preferred over npm. Refer to this comparison if you want to <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.section.io/engineering-education/npm-vs-npx/">learn more</a>.</p><p><strong>Run the Development Server</strong></p><p>You now have a new directory called <code>web3-demo</code>. Let’s <code>cd</code> into it:</p><pre data-type="codeBlock" text="cd web3-demo
"><code><span class="hljs-built_in">cd</span> web3-demo
</code></pre><p>Then, run the following command:</p><pre data-type="codeBlock" text="npm run dev
"><code>npm run dev
</code></pre><p>This starts your Next.js app’s &quot;development server&quot; (more on this later) on port <strong>3000</strong>.</p><p>Let’s check to see if it’s working. Open <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="http://localhost:3000/">http://localhost:3000</a> from your browser.</p><p>You should see something like this:</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/321ec4459d988960552b8544e324e498970c05abde1395ab09000edefded966a.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><h3 id="h-integrate-web3js-with-web-application" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Integrate web3.js with Web Application</h3><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://web3js.readthedocs.io/en/v1.5.2/">web3.js</a> is a collection of libraries that allow you to interact with a local or remote ethereum node using HTTP, IPC or WebSocket. In our application, we use web3.js to interact with the ETH account on MetaMask.</p><p>First you need to get web3.js into your project. This can be done using the following methods:</p><ul><li><p>npm: <code>npm install web3</code></p></li><li><p>yarn: <code>yarn add web3</code></p></li><li><p>pure js: link the <code>dist/web3.min.js</code></p></li></ul><p>After that you need to create a web3 instance and set a provider.</p><p>Most Ethereum-supported browsers like MetaMask have an <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://eips.ethereum.org/EIPS/eip-1193">EIP-1193</a> compliant provider available at <code>window.ethereum</code>.</p><p>For web3.js, check <code>Web3.givenProvider</code>.</p><p>If this property is <code>null</code> you should connect to a remote/local node.</p><pre data-type="codeBlock" text="// In Node.js use: 
import Web3 from &quot;web3&quot;;
const web3 = new Web3(Web3.givenProvider || &quot;ws://localhost:8545&quot;);
"><code><span class="hljs-comment">// In Node.js use: </span>
<span class="hljs-keyword">import</span> <span class="hljs-title">Web3</span> <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"web3"</span>;
const web3 <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> Web3(Web3.givenProvider <span class="hljs-operator">|</span><span class="hljs-operator">|</span> <span class="hljs-string">"ws://localhost:8545"</span>);
</code></pre><p>That’s it! now you can use the <code>web3</code> object.</p><p><strong>Main UI Components</strong></p><ul><li><p><strong>Show me the money!</strong> title</p></li><li><p>A button to connect with MetaMask</p></li><li><p>A button to show the ETH balance</p></li></ul><p><strong>Initial Landing Page</strong></p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/2403f7d6ac9b1672764bcd334b4a647872609c41a5b9b261c32d6bed6edd93e3.png" alt="Landing Page" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Landing Page</figcaption></figure><p>After the <strong>Connect With MetaMask</strong> button is clicked, if you have already logged in Metamask, the button text changes to <strong>Show ETH Balance</strong>. You can clicked the <strong>Show ETH Balance</strong> button to see the balance of your test ETH as shown below:</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/1b562fd20a831e274077b8dbcc203aab2638e35bc7a9e436397a5a06a8320b9c.png" alt="Show ETH Balance" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Show ETH Balance</figcaption></figure><p>If you haven’t signed in to MetaMask, After the <strong>Connect With MetaMask</strong> button is clicked, MetaMask will prompt you to log in, as shown below:</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/987fc5782915a006d33760adfca981bf2d195fb9e53bada7904d2c01d6fedffd.png" alt="Required Permission to Sign in" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Required Permission to Sign in</figcaption></figure><p>After you log in, the button text changes to <strong>Show ETH Balance</strong>. You can clicked the <strong>Show ETH Balance</strong> button to see the balance of your test ETH.</p><p><strong>Main Code Block</strong></p><pre data-type="codeBlock" text="import Head from &apos;next/head&apos;
import { useState } from &apos;react&apos;;
import Web3 from &quot;web3&quot;;

export default function Home() {
  const [metaMaskConnected, setMetaMaskConnected] = useState(false);
  const [accounts, setAccounts] = useState([]);
  const [showCurrentBalance, setShowCurrentBalance] = useState(false);

  let web3 = new Web3();
  const ethEnabled = async () =&gt; {
    if (window.ethereum) {
      await window.ethereum.send(&apos;eth_requestAccounts&apos;);
      web3 = new Web3(window.ethereum);
      return true;
    }
    return false;
  };

  const checkAccounts = async () =&gt; {
    if (!await ethEnabled()) {
      alert(&quot;Please install MetaMask to use this dApp!&quot;);
    }
    let accs = await web3.eth.getAccounts();
    const newAccounts = await Promise.all(accs.map(async address =&gt; {
      const balance = await web3.eth.getBalance(address);
      return web3.utils.fromWei(balance, &apos;ether&apos;);
    }));
    setAccounts(newAccounts);
  };

  const showBalance = async () =&gt; {
    await checkAccounts();
    setShowCurrentBalance(true);
  };

  const onClickConnect = async () =&gt; {
    await checkAccounts();
    setMetaMaskConnected(true);
  }


  return (
    &lt;div className=&quot;container&quot;&gt;
      &lt;Head&gt;
        &lt;title&gt;Create Next App&lt;/title&gt;
        &lt;link rel=&quot;icon&quot; href=&quot;/favicon.ico&quot; /&gt;
      &lt;/Head&gt;

      &lt;main&gt;
        &lt;h1 className=&quot;title&quot;&gt;
          Show me the money!
        &lt;/h1&gt;
        &lt;button className=&quot;button&quot; style={{display: metaMaskConnected ? &quot;none&quot; : &quot;block&quot;}} onClick={onClickConnect}&gt;Connect With MetaMask&lt;/button&gt;
        &lt;button className=&quot;button&quot; style={{display: metaMaskConnected ? &quot;block&quot; : &quot;none&quot;}} onClick={showBalance}&gt;Show ETH Balance&lt;/button&gt;
        &lt;p style={{display: showCurrentBalance &amp;&amp; accounts.length &gt; 0 ? &quot;block&quot; : &quot;none&quot;}}&gt;Current ETH Balance: {parseFloat(accounts[0]).toFixed(2)}&lt;/p&gt;
        &lt;p style={{display: showCurrentBalance &amp;&amp; accounts.length === 0 ? &quot;block&quot; : &quot;none&quot;, color: &quot;red&quot;}}&gt;Please connect your test account!&lt;/p&gt;

      &lt;/main&gt;
    &lt;/div&gt;
  )
}
"><code><span class="hljs-keyword">import</span> <span class="hljs-title">Head</span> <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">'next/head'</span>
<span class="hljs-title"><span class="hljs-keyword">import</span></span> { <span class="hljs-title">useState</span> } <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-title">Web3</span> <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"web3"</span>;

export default <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Home</span>(<span class="hljs-params"></span>) </span>{
  const [metaMaskConnected, setMetaMaskConnected] <span class="hljs-operator">=</span> useState(<span class="hljs-literal">false</span>);
  const [accounts, setAccounts] <span class="hljs-operator">=</span> useState([]);
  const [showCurrentBalance, setShowCurrentBalance] <span class="hljs-operator">=</span> useState(<span class="hljs-literal">false</span>);

  let web3 <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> Web3();
  const ethEnabled <span class="hljs-operator">=</span> async () <span class="hljs-operator">=</span><span class="hljs-operator">></span> {
    <span class="hljs-keyword">if</span> (window.ethereum) {
      await window.ethereum.<span class="hljs-built_in">send</span>(<span class="hljs-string">'eth_requestAccounts'</span>);
      web3 <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> Web3(window.ethereum);
      <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
    }
    <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
  };

  const checkAccounts <span class="hljs-operator">=</span> async () <span class="hljs-operator">=</span><span class="hljs-operator">></span> {
    <span class="hljs-keyword">if</span> (<span class="hljs-operator">!</span>await ethEnabled()) {
      alert(<span class="hljs-string">"Please install MetaMask to use this dApp!"</span>);
    }
    let accs <span class="hljs-operator">=</span> await web3.eth.getAccounts();
    const newAccounts <span class="hljs-operator">=</span> await Promise.all(accs.map(async <span class="hljs-keyword">address</span> <span class="hljs-operator">=</span><span class="hljs-operator">></span> {
      const balance <span class="hljs-operator">=</span> await web3.eth.getBalance(<span class="hljs-keyword">address</span>);
      <span class="hljs-keyword">return</span> web3.utils.fromWei(balance, <span class="hljs-string">'ether'</span>);
    }));
    setAccounts(newAccounts);
  };

  const showBalance <span class="hljs-operator">=</span> async () <span class="hljs-operator">=</span><span class="hljs-operator">></span> {
    await checkAccounts();
    setShowCurrentBalance(<span class="hljs-literal">true</span>);
  };

  const onClickConnect <span class="hljs-operator">=</span> async () <span class="hljs-operator">=</span><span class="hljs-operator">></span> {
    await checkAccounts();
    setMetaMaskConnected(<span class="hljs-literal">true</span>);
  }


  <span class="hljs-keyword">return</span> (
    <span class="hljs-operator">&#x3C;</span>div className<span class="hljs-operator">=</span><span class="hljs-string">"container"</span><span class="hljs-operator">></span>
      <span class="hljs-operator">&#x3C;</span>Head<span class="hljs-operator">></span>
        <span class="hljs-operator">&#x3C;</span>title<span class="hljs-operator">></span>Create Next App<span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>title<span class="hljs-operator">></span>
        <span class="hljs-operator">&#x3C;</span>link rel<span class="hljs-operator">=</span><span class="hljs-string">"icon"</span> href<span class="hljs-operator">=</span><span class="hljs-string">"/favicon.ico"</span> <span class="hljs-operator">/</span><span class="hljs-operator">></span>
      <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>Head<span class="hljs-operator">></span>

      <span class="hljs-operator">&#x3C;</span>main<span class="hljs-operator">></span>
        <span class="hljs-operator">&#x3C;</span>h1 className<span class="hljs-operator">=</span><span class="hljs-string">"title"</span><span class="hljs-operator">></span>
          Show me the money<span class="hljs-operator">!</span>
        <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>h1<span class="hljs-operator">></span>
        <span class="hljs-operator">&#x3C;</span>button className<span class="hljs-operator">=</span><span class="hljs-string">"button"</span> style<span class="hljs-operator">=</span>{{display: metaMaskConnected ? <span class="hljs-string">"none"</span> : <span class="hljs-string">"block"</span>}} onClick<span class="hljs-operator">=</span>{onClickConnect}<span class="hljs-operator">></span>Connect With MetaMask<span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>button<span class="hljs-operator">></span>
        <span class="hljs-operator">&#x3C;</span>button className<span class="hljs-operator">=</span><span class="hljs-string">"button"</span> style<span class="hljs-operator">=</span>{{display: metaMaskConnected ? <span class="hljs-string">"block"</span> : <span class="hljs-string">"none"</span>}} onClick<span class="hljs-operator">=</span>{showBalance}<span class="hljs-operator">></span>Show ETH Balance<span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>button<span class="hljs-operator">></span>
        <span class="hljs-operator">&#x3C;</span>p style<span class="hljs-operator">=</span>{{display: showCurrentBalance <span class="hljs-operator">&#x26;</span><span class="hljs-operator">&#x26;</span> accounts.<span class="hljs-built_in">length</span> <span class="hljs-operator">></span> <span class="hljs-number">0</span> ? <span class="hljs-string">"block"</span> : <span class="hljs-string">"none"</span>}}<span class="hljs-operator">></span>Current ETH Balance: {parseFloat(accounts[<span class="hljs-number">0</span>]).toFixed(<span class="hljs-number">2</span>)}<span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>p<span class="hljs-operator">></span>
        <span class="hljs-operator">&#x3C;</span>p style<span class="hljs-operator">=</span>{{display: showCurrentBalance <span class="hljs-operator">&#x26;</span><span class="hljs-operator">&#x26;</span> accounts.<span class="hljs-built_in">length</span> <span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-number">0</span> ? <span class="hljs-string">"block"</span> : <span class="hljs-string">"none"</span>, color: <span class="hljs-string">"red"</span>}}<span class="hljs-operator">></span>Please connect your test account<span class="hljs-operator">!</span><span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>p<span class="hljs-operator">></span>

      <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>main<span class="hljs-operator">></span>
    <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>div<span class="hljs-operator">></span>
  )
}
</code></pre><p><strong>Triggering the Log In UI of MetaMask</strong></p><p>The critical piece of the code which triggers the Log In UI of MetaMask is <code>await window.ethereum.send(&apos;eth_requestAccounts&apos;)</code>. If the MetaMask is already connected, this operation succeeds silently. Otherwise, the MetaMask Log In UI will pop up, asking for permission.</p><p><strong>Collecting the active account and ETH balance</strong></p><p>The piece of code which collects the active is <code>let accs = await web3.eth.getAccounts()</code>. I originally thought the <code>getAccounts()</code> method will return either an empty array or an array of all the available accounts. But according to <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.metamask.io/guide/ethereum-provider.html#accountschanged">MetaMask Doc</a>, the <code>getAccounts()</code> method returns an array that is either empty or contains a single account address. The returned address, if any, is the address of the most recently used account that the caller is permitted to access. That seems like a security feature. Whether it will return all the available accounts in the future is TBD.</p><p>The following code records the ETH balance for the active account</p><pre data-type="codeBlock" text="    const newAccounts = await Promise.all(accs.map(async address =&gt; {
      const balance = await web3.eth.getBalance(address);
      return web3.utils.fromWei(balance, &apos;ether&apos;);
    }));
"><code>    const newAccounts <span class="hljs-operator">=</span> await Promise.all(accs.map(async <span class="hljs-keyword">address</span> <span class="hljs-operator">=</span><span class="hljs-operator">></span> {
      const balance <span class="hljs-operator">=</span> await web3.eth.getBalance(<span class="hljs-keyword">address</span>);
      <span class="hljs-keyword">return</span> web3.utils.fromWei(balance, <span class="hljs-string">'ether'</span>);
    }));
</code></pre><p><strong>Toggling Between Different Accounts</strong></p><p>It is possible that you have multiple accounts connected to your application as shown below:</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/4e29b664602342d9e38b827fdf7bcdfd19e0f67b08bad17d71b5cbf487d0ff4e.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>You can click the “Connected“ button, and switch to the desired account. After that, you can click the <strong>Show ETH Balance</strong> button again to see the ETH balance of the new active account.</p><h2 id="h-conclusion" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Conclusion</h2><p>In this article, we’ve demonstrated how to create a simple web application using Next.js, web3.js, and MetaMask. You have learned how to create a MetaMask wallet, how to deposit test ETH to your wallet, how to use web3.js to show the ETH balance.</p><p>I hope you learn something very interesting and fundamental about Web3. Obviously, this web application is just a tip of the Web3 ice berg, and there is so much more you can achieve in the Web3 world.</p><p>If you find this article helpful, please follow my Twitter <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/harrywangw">@harrywangw</a>. Let’s rock the Web3 world together.</p><h2 id="h-resources" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Resources</h2><p>The complete code resides in Github: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/totolo/web3-demo">web3-demo</a></p>]]></content:encoded>
            <author>harrywang@newsletter.paragraph.com (Explorer of things)</author>
        </item>
    </channel>
</rss>