<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Bhaskar </title>
    <description>The latest articles on DEV Community by Bhaskar  (@bhaskardutta).</description>
    <link>https://dev.to/bhaskardutta</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%2F829772%2F18507628-f70b-48bd-ad51-ea1dd746fd7a.jpeg</url>
      <title>DEV Community: Bhaskar </title>
      <link>https://dev.to/bhaskardutta</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bhaskardutta"/>
    <language>en</language>
    <item>
      <title>What is the right way to do microservice ??</title>
      <dc:creator>Bhaskar </dc:creator>
      <pubDate>Fri, 03 May 2024 19:23:26 +0000</pubDate>
      <link>https://dev.to/bhaskardutta/what-is-the-right-way-to-do-microservice--3no9</link>
      <guid>https://dev.to/bhaskardutta/what-is-the-right-way-to-do-microservice--3no9</guid>
      <description>&lt;p&gt;I am exploring microservice-based architecture and have a doubt:&lt;/p&gt;

&lt;h3&gt;
  
  
  Should all my microservices have a common database?
&lt;/h3&gt;

&lt;p&gt;While designing the application, I can take either of the following two approaches:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgbgsabpi93wj0butz3vc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgbgsabpi93wj0butz3vc.png" alt="Approach 1" width="800" height="568"&gt;&lt;/a&gt;&lt;br&gt;
Approach 1: All microservices have a common database&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;With approach 1:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I can take advantage of the relational schema of the database.&lt;/li&gt;
&lt;li&gt;However, since the database is common, when it comes to scalability, I am afraid it would act as a bottleneck.&lt;/li&gt;
&lt;li&gt;Also there would be unnecessary code duplications and I don’t think this approach falls in line with the mantra of “Separation of Concern”, that is the main motivation behind choosing microservices in first place.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;whereas with approach 2:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I think this approach would be more scalable and easier to maintain separation of concern.&lt;/li&gt;
&lt;li&gt;However, with this approach I don’t get to enjoy the benefits of Relational Schema which would add to the code complexity.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Dear readers, I understand that the system requirements play a significant role in making any design decision, however I wonder, which of this two approaches would be more preferred in terms of scalability and be considered to be a better system design?&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>beginners</category>
      <category>discuss</category>
      <category>microservices</category>
    </item>
    <item>
      <title>Biconomy - Win your customer's heart with Gasless Transactions</title>
      <dc:creator>Bhaskar </dc:creator>
      <pubDate>Mon, 05 Dec 2022 03:32:41 +0000</pubDate>
      <link>https://dev.to/bhaskardutta/biconomy-win-your-customers-heart-with-gasless-transactions-3ak2</link>
      <guid>https://dev.to/bhaskardutta/biconomy-win-your-customers-heart-with-gasless-transactions-3ak2</guid>
      <description>&lt;p&gt;Gas Price is a necessary evil in the world of Web3. Although it plays a vital role in terms of rewarding the “Miners” and making smart contract execution more secure, it creates an awful user experience. Even from a purely business perspective, it makes much more sense in having a fixed billing system for the users, while the execution costs are covered by the service provider. With the traditional approach, it’s impossible to build such a system without introducing a centralized entity into the system. &lt;/p&gt;

&lt;h2&gt;
  
  
  💡Biconomy - A ray of hope
&lt;/h2&gt;

&lt;p&gt;Among other features, Biconomy makes it possible for developers to provide “Gasless Transactions” with the least amount of effort. This is a fully decentralized solution powered by smart contracts and no compromise is made in terms of security and stability.&lt;/p&gt;

&lt;p&gt;Biconomy is based on the simple concept that the service provider pays the gas on behalf of the users. The users are only required to sign a particular message while interacting with the smart contract. This signature is then validated by Biconomy and if sufficient funds are available to sponsor the transaction, the gas is paid, and the transaction details are forwarded to the Dapp smart contract.&lt;/p&gt;

&lt;p&gt;The important point to note is that there is nothing like a transaction without gas fees, however, Biconomy just enables us to maintain a special account where we deposit enough funds to pay for the gas price for all users. The gas price gets paid from this “&lt;em&gt;special&lt;/em&gt;” account and it’s up to us or the project admin to ensure that sufficient funds are always available for sponsoring transactions. To make this even simpler, Biconomy provides an intuitive Dashboard for managing everything.&lt;/p&gt;

&lt;h2&gt;
  
  
  🎯Scope of this article
&lt;/h2&gt;

&lt;p&gt;This article will act as a beginner-friendly tutorial for getting started with Biconomy. For the sake of simplicity, we will be focusing only on &lt;em&gt;&lt;a href="https://docs.biconomy.io/products/enable-gasless-transactions" rel="noopener noreferrer"&gt;Gasless Transactions&lt;/a&gt;&lt;/em&gt;, specifically &lt;em&gt;&lt;a href="https://docs.biconomy.io/products/enable-gasless-transactions/choose-an-approach-to-enable-gasless/eip-2771" rel="noopener noreferrer"&gt;Gasless Transactions using EIP 2771-based approach&lt;/a&gt;&lt;/em&gt;. This article won’t discuss the architecture used by Biconomy nor the various other jaw-dropping features provided. To learn about them I recommend giving their &lt;a href="https://docs.biconomy.io/" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt; a read. &lt;/p&gt;

&lt;p&gt;In this tutorial we will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Write a simple Smart Contract using &lt;code&gt;EIP 2771&lt;/code&gt; to make it compatible with Biconomy.&lt;/li&gt;
&lt;li&gt;Deploy and test our smart contract on the Polygon Testnet (Mumbai).&lt;/li&gt;
&lt;li&gt;Build a very simple front end using React to interact with our smart contract.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I follow a “&lt;em&gt;code-first-explanation-next”&lt;/em&gt; approach. Please let me know if this is helpful or if I should try any different approach in the comment section.&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚠️Disclaimer
&lt;/h2&gt;

&lt;p&gt;At the point of writing this article, Biconomy is transitioning to a newer SDK-based approach that brings yet more to the table, however here we will be using the older approach which is much simpler and sufficient for our needs. Documentation of the latest SDK can be found &lt;a href="https://biconomy.gitbook.io/sdk/introduction/overview" rel="noopener noreferrer"&gt;here&lt;/a&gt;. The new SDK is still WIP and not polished enough for developers to use. Once ready, I plan to cover it in my future articles. &lt;/p&gt;

&lt;h2&gt;
  
  
  🎒Pre-requisites
&lt;/h2&gt;

&lt;p&gt;I know you all are excited to get started, but before we dive in, make sure you got the following pre-requisites sorted:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://remix.ethereum.org/#optimize=false&amp;amp;runs=200&amp;amp;evmVersion=null&amp;amp;version=soljson-v0.8.7+commit.e28d00a7.js" rel="noopener noreferrer"&gt;Remix IDE&lt;/a&gt;: For developing smart contracts&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://chrome.google.com/webstore/detail/metamask/nkbihfbeogaeaoehlefnkodbefgpgknn" rel="noopener noreferrer"&gt;Metamask&lt;/a&gt;: Metamask is a popular non-custodial wallet used for interacting with the blockchain.&lt;/li&gt;
&lt;li&gt;Connected with Testnet: Although you can use any network of your choice, I will be using Polygon’s Mumbai Testnet. If you want to follow along, make sure you have added Mumbai Testnet in Metamask following &lt;a href="https://medium.com/stakingbits/how-to-connect-polygon-mumbai-testnet-to-metamask-fc3487a3871f" rel="noopener noreferrer"&gt;this article&lt;/a&gt;, and then fund your account using &lt;a href="https://www.notion.so/Write-ups-620aeda4ab7649908b58b692a6de981c" rel="noopener noreferrer"&gt;this faucet&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  💻Writing the Smart Contract
&lt;/h2&gt;

&lt;p&gt;Let’s get started with the crux of our project, i.e., the smart contract. In your Remix IDE create a new file named &lt;code&gt;Greetings.sol&lt;/code&gt; and paste the following code.&lt;br&gt;
&lt;/p&gt;

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

contract Greetings {
    mapping (address =&amp;gt; string) public greetings;

    function setGreeting(string memory newGreeting) public {
        greetings[msg.sender] = newGreeting;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a very simple smart contract that stores a string each corresponding to each address that called the &lt;code&gt;setGreeting&lt;/code&gt;function. The string to be stored is passed as an argument to the function. The important point to note here is &lt;code&gt;msg.sender&lt;/code&gt; is used for finding the account address that invoked the &lt;code&gt;setGreeting&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;Let’s try to understand the challenge of using the above contract with Biconomy. Refer to the following diagram to understand how Biconomy forwards transactions:&lt;br&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%2Fjs90t7eqqp8qnijvc21q.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%2Fjs90t7eqqp8qnijvc21q.png" alt="Biconomy TrustedForwarder" width="800" height="270"&gt;&lt;/a&gt;&lt;br&gt;
If you look closely, you will understand that a “&lt;em&gt;TrustedForwarder&lt;/em&gt;” contract is used to invoke our smart contract. In this scenario, regardless of which account initiates the call, the &lt;code&gt;msg.sender&lt;/code&gt; will always return the address of the caller, i.e., the &lt;em&gt;TrustedForwarder’s&lt;/em&gt; address. To solve this issue, we have to make the following changes to our smart contract:&lt;br&gt;
&lt;/p&gt;

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

import "@openzeppelin/contracts/metatx/ERC2771Context.sol";

contract Greetings is ERC2771Context {

    constructor(address trustedForwarderAddress) ERC2771Context(trustedForwarderAddress) {}

    mapping (address =&amp;gt; string) public greetings;

    function setGreeting(string memory newGreeting) public {
        greetings[_msgSender()] = newGreeting;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we are doing the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We are using the &lt;code&gt;ERC2771Context&lt;/code&gt; contract from OpenZeppelin contracts. It provides us with the &lt;code&gt;_msgSender()&lt;/code&gt; function that will be very important to us.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The &lt;code&gt;trustedForwarderAddress&lt;/code&gt; is the contract that we expect to call our smart contract. This forwarder is responsible for signature verification and protection against replay attacks. Before forwarding the transaction, the signer (our user’s address) is appended to the &lt;em&gt;calldata and&lt;/em&gt; passed to the smart contact. The &lt;code&gt;_msgSender()&lt;/code&gt; function returns this address.&lt;/p&gt;

&lt;p&gt;You can find the list of Biconomy’s TrustedForwarder’s addresses &lt;a href="https://docs.biconomy.io/misc/contract-addresses" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Inside our code we replace &lt;code&gt;msg.sender&lt;/code&gt; with &lt;code&gt;_msgSender()&lt;/code&gt; to reflect the correct user.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;And with that our smart contract is ready for gasless transactions!!&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Deployment and Biconomy Setup
&lt;/h3&gt;

&lt;p&gt;Now that our smart contract is ready, it’s time to deploy our smart contract. Let’s deploy it to Mumbai Testnet (You can choose any other network of your choice).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In the deploy section of Remix, select &lt;code&gt;Injected Provider - MetaMask&lt;/code&gt; as the Environment. Also, make sure your Metamask is connected with your desired chain.&lt;/li&gt;
&lt;li&gt;For your chosen chain, find the respective TrustedForwarder address &lt;a href="https://docs.biconomy.io/misc/contract-addresses" rel="noopener noreferrer"&gt;here&lt;/a&gt;. Since I am using Mumbai Testnet, mine is 0x69015912AA33720b842dCD6aC059Ed623F28d9f7. You must pass this address as a constructor argument while deploying the contract.&lt;/li&gt;
&lt;li&gt;Finally, click on &lt;code&gt;transact&lt;/code&gt; and confirm the MetaMask popup to deploy the smart contract.
&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%2F9iq6dmvdulgyag0m4qrs.png" alt="Deploying Smart Contract" width="631" height="766"&gt;
Now to set up Biconomy, sign in to your Biconomy Dashboard. Next, you have to register a new Dapp and mention the chain in which your smart contract is deployed.
&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%2Fifqf3scv3r42hwan0vmy.png" alt="Register new Dapp in Biconomy" width="800" height="430"&gt;
Once registered, click on the card corresponding to your Dapp and this will open the respective Dapp’s dashboard. Here you can see the various details associated with your Dapp.
&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%2F6uepfvayoquftiyhvbmk.png" alt="Newly registered Dapp" width="800" height="523"&gt;
For a freshly created Dapp, the Gas Balance would be 0. Before you can let users enjoy gasless transactions, you have to load crypto (native token) into this Dapp to pay for the gas on behalf of the users. Click on the &lt;code&gt;Fill Gas&lt;/code&gt; button, enter the amount of token you want to deposit, and click &lt;code&gt;Fill Me Up&lt;/code&gt;. A MetaMask popup will ask you to send the required amount of tokens and confirm it to deposit the funds. It should be reflected on your Dapp promptly under &lt;code&gt;GAS BALANCE&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A single Dapp can be associated with multiple smart contracts. Head to the &lt;code&gt;Smart Contract&lt;/code&gt; section in your dashboard. Enter the Name, address, and ABI of your smart contract. All these details can be found in Remix. Make sure that &lt;code&gt;Meta Transaction Type&lt;/code&gt; is set to &lt;code&gt;Trusted Forwarder&lt;/code&gt;. Click on &lt;code&gt;Add&lt;/code&gt; to add the smart contract to your Dapp.&lt;br&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%2Fvkcqbiscpykqpbcn6z4h.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%2Fvkcqbiscpykqpbcn6z4h.png" alt="Adding Smart Contract" width="800" height="601"&gt;&lt;/a&gt;&lt;br&gt;
Now the final step is to create API Endpoints for the function we want to invoke. Head to the &lt;code&gt;Dapp APIs&lt;/code&gt; section.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click on the white &lt;code&gt;Add&lt;/code&gt; Button&lt;/li&gt;
&lt;li&gt;Enter a suitable name for your API.&lt;/li&gt;
&lt;li&gt;Choose the corresponding Smart Contract and Method to be invoked.&lt;/li&gt;
&lt;li&gt;Click on the orange &lt;code&gt;Add&lt;/code&gt; button to create a new API endpoint.
&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%2F21zzx6yzk9dw2uhrov7t.png" alt="Creating new Endpoint" width="800" height="325"&gt;
Hurray!! Finally, we are ready for gasless transactions 👏👏👏.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  🌐Building a basic website
&lt;/h2&gt;

&lt;p&gt;Now that we are ready for gasless transactions, it’s time to build a simple website for interacting with our smart contract. In this tutorial, we are going to use React for building our demo website.&lt;/p&gt;

&lt;p&gt;Use the following command to create a new react project:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;I have named my project &lt;code&gt;biconomy_tutorial&lt;/code&gt;, however, feel free to choose any name of your liking. Once the project is initialized, move inside the newly created project folder. Next, we will be using the &lt;code&gt;biconomy/mexa&lt;/code&gt; package for interacting with our smart contract. Use the following command for installing it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @biconomy/mexa
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🚫Known Issue
&lt;/h3&gt;

&lt;p&gt;In case you have used any other libraries like &lt;code&gt;web3.js&lt;/code&gt;, you must be already familiar with the &lt;a href="https://github.com/bcnmy/gasless-playground/issues/2" rel="noopener noreferrer"&gt;Webpack Error&lt;/a&gt;. For those who are new, whenever you try to import the &lt;code&gt;biconomy/mexa&lt;/code&gt; package in your React code, you would get an error message similar to the following:&lt;br&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%2Fcdeytes3bqwjbz44w9zn.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%2Fcdeytes3bqwjbz44w9zn.png" alt="Webpack Error" width="800" height="528"&gt;&lt;/a&gt;&lt;br&gt;
To resolve this we will need &lt;code&gt;react-app-rewired&lt;/code&gt;. First, install the required dependencies using 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;npm &lt;span class="nb"&gt;install &lt;/span&gt;react-app-rewired crypto-browserify stream-browserify assert stream-http https-browserify os-browserify url path-browserify browserify-zlib process buffer util
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now create a new file called &lt;code&gt;config-overrides.js&lt;/code&gt; and paste in the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;webpack&lt;/span&gt; &lt;span class="o"&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="s1"&gt;webpack&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="nf"&gt;override&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ignoreWarnings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;/Failed to parse source map/&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;fallback&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fallback&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
  &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fallback&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;crypto&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="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;crypto-browserify&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;stream&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="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;stream-browserify&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;assert&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="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;assert&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;http&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="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;stream-http&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;https&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="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https-browserify&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;os&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="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;os-browserify&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;url&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="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;url&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;path&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="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;path-browserify&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;zlib&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="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;browserify-zlib&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;process&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="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;process/browser&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;buffer&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="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;buffer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;util&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="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;util&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;tls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;net&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fallback&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fallback&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;plugins&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;plugins&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;[]).&lt;/span&gt;&lt;span class="nf"&gt;concat&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;webpack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ProvidePlugin&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;process&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;process/browser&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;buffer&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="s1"&gt;Buffer&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally in the &lt;code&gt;package.json&lt;/code&gt; file change the &lt;code&gt;start&lt;/code&gt; task to &lt;code&gt;react-app-wired start&lt;/code&gt;. Finally, close and restart the react app. Now this problem should be resolved.&lt;/p&gt;

&lt;h3&gt;
  
  
  Building the website
&lt;/h3&gt;

&lt;p&gt;Open the &lt;code&gt;App.js&lt;/code&gt; file in our react project in any code editor of your choice and make the following modifications:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Biconomy&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;@biconomy/mexa&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ethers&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&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;setMessage&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;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"App"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;header&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"App-header"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello World&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Set Message&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;header&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&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;Here we added a simple button that calls the &lt;code&gt;setMessage&lt;/code&gt; function. This function takes a string as input and passes it to the smart contract function. For simplicity, here we are hardcoding the string to be “&lt;em&gt;Hello World&lt;/em&gt;”. To simplify our project even further, we will implement the complete logic of using Biconomy inside the &lt;code&gt;setMessage&lt;/code&gt; function, however, an experienced React developer would prefer to use proper state management.&lt;/p&gt;

&lt;p&gt;Before using Biconomy, we have to first initialize it. The code for initializing Biconomy is as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;setMessage&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;message&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;biconomy&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;Biconomy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ethereum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;5hUl....1a87&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;debug&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="na"&gt;contractAddresses&lt;/span&gt;&lt;span class="p"&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;0x160d3a01bf31cabbb6fcb60b5573bbad859e46c7&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;biconomy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above code snippet note that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;As the Ethereum provider, we are using &lt;code&gt;window.ethereum&lt;/code&gt;, i.e., the Ethereum object injected by the Metamask wallet. In case you want to use a different wallet, you have to modify it respectively. (Let me know in the comments if you want an example of using a different wallet).&lt;/li&gt;
&lt;li&gt;Make sure you enter your own API Key for Biconomy that you will find in the Biconomy Dashboard. Needless to say, instead of hardcoding it, it’s recommended to use environment variables.&lt;/li&gt;
&lt;li&gt;We also have to pass a list of contract addresses that we want to interact with. Ideally, this list will contain only those contract addresses that we want to interact with, and not all the contract addresses added to our dashboard.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The next step is to create a contract instance. The beauty of Biconomy is from here on, the process of interacting with the smart contract is similar to the traditional approach. I am using &lt;code&gt;ethers&lt;/code&gt;, however, in the official documentation, you will also find how to use &lt;code&gt;web3.js&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;setMessage&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;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;...&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;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Contract&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="nx"&gt;CONTRACT_ABI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;biconomy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ethersProvider&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;ethersProvider&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;ethers&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="nc"&gt;Web3Provider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ethereum&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;connectedAddress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;ethersProvider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listAccounts&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;tx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;contractInstance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;populateTransaction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setGreeting&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;gasLimit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1000000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;gasPrice&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1000000000&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;txDetails&lt;/span&gt; &lt;span class="o"&gt;=&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;contractAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CONTRACT_ADDRESS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;signatureType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;PERSONAL_SIGN&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;provider&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;biconomy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;provider&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;provider&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;eth_sendTransaction&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;txDetails&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we are performing the following tasks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creating an instance of the smart contract.&lt;/li&gt;
&lt;li&gt;We get and store the current connected Metamask account in the &lt;code&gt;connectedAddress&lt;/code&gt; variable.&lt;/li&gt;
&lt;li&gt;Next, we define the transaction and store it in &lt;code&gt;tx&lt;/code&gt; variable. Note that here we are not sending the transaction to the blockchain. Rather we are using the &lt;code&gt;populateTransaction&lt;/code&gt; method because we want to generate the calldata that would be sent to the blockchain.&lt;/li&gt;
&lt;li&gt;Any function invocation in the blockchain is also recorded in form of a transaction. Without getting into the complexities, you can assume that what differentiates a transfer of native tokens (also called transaction) and calling a function is that in the latter, a signed payload containing the function signature and the arguments are passed which is also termed as the &lt;code&gt;calldata&lt;/code&gt;. We generate these transaction details and store them in the &lt;code&gt;txDetails&lt;/code&gt; variable.&lt;/li&gt;
&lt;li&gt;Next, we obtain the &lt;code&gt;provider&lt;/code&gt; from the defined &lt;code&gt;Biconomy&lt;/code&gt; object.&lt;/li&gt;
&lt;li&gt;Finally, we send the transaction for verification to the blockchain. Here we use the &lt;code&gt;eth_sendTransaction&lt;/code&gt; function. This is where the users receive a Metamask popup asking them to sign a specific payload. Behind the hood, this transaction payload is actually passed by the &lt;em&gt;Biconomy Relay&lt;/em&gt; to the &lt;em&gt;TrustedForwarder&lt;/em&gt; contract, and it also pays for the required gas.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With this, you are now ready to make Gasless transactions 😎. Go ahead and give your newly created website a try. I have a small task for you:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;👉Try to make a gasless transaction. Verify whether the message was set properly and
whether the user had to pay any gas.

👉Let me know your findings in the comment section
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In case you run into errors or feel I was not able to explain the topic properly, please let me know and I will try my best to clear every doubt.&lt;/p&gt;

&lt;h2&gt;
  
  
  👨‍💻About Me
&lt;/h2&gt;

&lt;p&gt;Hi, I am &lt;a href="https://www.linkedin.com/in/itsbhaskardutta/" rel="noopener noreferrer"&gt;Bhaskar Dutta&lt;/a&gt;, a Software Developer here at &lt;a href="https://xenabler.digital/" rel="noopener noreferrer"&gt;Xenabler&lt;/a&gt; where we try to bring technology and people together, one commit at a time.&lt;/p&gt;

&lt;p&gt;If you have read so far, I feel we are going to be partners in an otherwise long journey of exploring the ever-changing world of technology. I would really want to connect with my readers and know them a bit more and if you want something similar, do send a connect request on &lt;a href="https://www.linkedin.com/in/itsbhaskardutta/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Before saying goodbye, remember to take care of yourself and let the special people in your life know you &lt;em&gt;Love Them&lt;/em&gt;. We will soon meet again in a different tutorial, till then &lt;em&gt;Take Care of Yourself&lt;/em&gt;, let the special people in your life know you &lt;em&gt;Love Them&lt;/em&gt;, and &lt;em&gt;Keep Building&lt;/em&gt;.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>learning</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Signing message using Metamask in Flutter</title>
      <dc:creator>Bhaskar </dc:creator>
      <pubDate>Tue, 28 Jun 2022 23:29:16 +0000</pubDate>
      <link>https://dev.to/bhaskardutta/signing-message-using-metamask-in-flutter-1o37</link>
      <guid>https://dev.to/bhaskardutta/signing-message-using-metamask-in-flutter-1o37</guid>
      <description>&lt;p&gt;When it comes to decentralized applications, signed messages provide a way to authenticate a user or specific data. It plays a crucial role when it comes to meta-transactions (off-chain transactions) and helps in preventing &lt;a href="https://medium.com/cypher-core/replay-attack-vulnerability-in-ethereum-smart-contracts-introduced-by-transferproxy-124bf3694e25" rel="noopener noreferrer"&gt;Replay Attacks&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we are going to build?
&lt;/h2&gt;

&lt;p&gt;This blog is a continuation of our &lt;a href="https://dev.to/bhaskardutta/building-with-flutter-and-metamask-8h5"&gt;Building with Flutter and Metamask&lt;/a&gt; series where we learn how to build an app that can directly interact with the blockchain using Metamask. In this blog, we will learn how we can use Metamask to sign a particular message. After this tutorial, there will have an additional “Sign Message” step in the login process.&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%2Fkg84gsxge6appteuauss.gif" 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%2Fkg84gsxge6appteuauss.gif" alt="Signing Message GIF"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The user signing the message represents the user agrees to the Terms and Conditions provided by our app. While building this feature, we will also learn about how these signatures are verified by the t contracts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why sign a message?
&lt;/h2&gt;

&lt;p&gt;A signature is the most common form to denote authorization. For example, in the real world, signing any legal document implies that the signer agrees to all the terms and conditions mentioned in the signed document. In the blockchain ecosystem, providing a signature implies a similar meaning. The user is asked to sign a message, and this signature can be later verified by the smart contract for performing several actions. &lt;a href="https://morten.dev/posts/the-magic-of-digital-signatures-on-ethereum" rel="noopener noreferrer"&gt;The Magic of Digital Signature on Ethereum&lt;/a&gt; provides an in-depth view of digital signature and signature verification.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://eips.ethereum.org/EIPS/eip-191" rel="noopener noreferrer"&gt;EIP-191&lt;/a&gt; and &lt;a href="https://eips.ethereum.org/EIPS/eip-712" rel="noopener noreferrer"&gt;EIP-712&lt;/a&gt; are two of the most popular proposed standardization for signing messages in the Ethereum blockchain ecosystem. EIP-712 provides a more human-readable format of data while signing it, whereas EIP-191 is much more simple in implementing but users are asked to sign a hash, that is difficult to comprehend. Although EIP-712 provides a far superior user experience, it is still in its early stages of development.&lt;/p&gt;

&lt;p&gt;For this tutorial, we will keep it very simple and provide our users with a hash of a simple text message for signing. We can also provide the raw text for signing, but this would make the process of signature verification more difficult as we must pass the length of the message signed for verification. We use &lt;code&gt;keccak256&lt;/code&gt; for hashing the message before signing it. Using &lt;code&gt;keccak256&lt;/code&gt; for hashing the message ensures that the hash will always be 256-bits long, regardless of the actual length of the message. It makes the process of signature verification significantly easier as the length of the signed message will always be 256-bit long. This will be more clear as we proceed with our application development and testing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pre-requisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Readers are highly encouraged to complete the &lt;a href="https://dev.to/bhaskardutta/building-with-flutter-and-metamask-8h5"&gt;first part&lt;/a&gt; of this series.&lt;/li&gt;
&lt;li&gt;Have all the pre-requisites mentioned in the first part.&lt;/li&gt;
&lt;li&gt;You can continue with your code, however, in this tutorial, we will start from &lt;code&gt;login-with-metamask&lt;/code&gt; branch of the &lt;a href="https://github.com/BhaskarDutta2209/FlutterAppWithMetamask" rel="noopener noreferrer"&gt;FlutterAppWithMetamask&lt;/a&gt; repo.&lt;/li&gt;
&lt;li&gt;Remix-ide for writing and testing smart contracts.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to use signatures
&lt;/h2&gt;

&lt;p&gt;Before we proceed with our application development, it is important to understand how messages are signed and verified using a smart contract. Let’s assume we want to sign the message “Hello Developers!”, the steps followed for this are shown in the following diagram:&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%2Ffntnph22em2kj4uz5lcy.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%2Ffntnph22em2kj4uz5lcy.png" alt="Flow Diagram for signing message"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The steps followed here are as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We start with the Raw data, in this example, it is the string “Hello Developers!”. In more advanced situations, the raw data can be something like serialized JSON.&lt;/li&gt;
&lt;li&gt;We use the keccak256 hashing algorithm to generate the hash of the Raw message. It is important to note that the generated hash is in form of a hexadecimal number.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Before signing, the passed message is structured in the following format:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"\x19Ethereum Signed Message:\n" + length(message) + message
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;The prefix denotes that the signed message is intended to be used in the Ethereum blockchain network. Since we are already hashing the raw message before passing it for signing, we know that the size of the &lt;code&gt;message&lt;/code&gt; will be &lt;code&gt;32 bytes&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Hence if we follow the above format of hashing the raw message before sending it to get signed, we can deterministically say that the prefix will always be &lt;code&gt;“\xEthereum Signed Message:\n32”&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finally, the formatted message is signed using the private key and a signature is produced in hexadecimal number format.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Using solidity, we can write a function that will take in the generated signature and the raw message to compute the account that signed the message. This forms a basis to verify whether the concerned account has provided the required signatures.&lt;/p&gt;

&lt;h3&gt;
  
  
  Signature verification using solidity
&lt;/h3&gt;

&lt;p&gt;Although writing a smart contract for signature verification is a complex topic and demands a tutorial of its own, the following YouTube video proves to be very helpful:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=vYwYe-Gv_XI&amp;amp;t=647s" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=vYwYe-Gv_XI&amp;amp;t=647s&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I will use a smart contract similar to the one shown in the tutorial for demonstrating the above-explained idea and testing the generated signature in a later phase of this blog. The smart contract I am using is:&lt;br&gt;
&lt;/p&gt;

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

pragma solidity ^0.8.4;

contract SignaturesInEth {

    function _split(bytes memory signature) internal pure returns(bytes32 r, bytes32 s, uint8 v) {
        require(signature.length == 65, "Signature must be 65 bytes long");
        assembly {
            r := mload(add(signature, 32))
            s := mload(add(signature, 64))
            v := byte(0, mload(add(signature, 96)))
        }
    }

    function getMessageHash(string memory message) public pure returns(bytes32) {
        return keccak256(abi.encodePacked(message));
    }

    function getEthSignedMessageHash(bytes32 messageHash) public pure returns(bytes32) {
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", messageHash));
    }

    function recover(bytes32 ethSignedMessageHash, bytes memory signature) public pure returns(address) {
        (bytes32 r, bytes32 s, uint8 v) = _split(signature);
        return ecrecover(ethSignedMessageHash, v, r, s);
    }

    function verifySignature(string memory message, bytes memory signature) public pure returns(address) {
        bytes32 messageHash = getMessageHash(message);
        bytes32 ethSignedMessageHash = getEthSignedMessageHash(messageHash);

        return recover(ethSignedMessageHash, signature);
    }

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Sample verification
&lt;/h3&gt;

&lt;p&gt;Let’s take a small tangent and verify the details shown in the above flow diagram. The details shown in the flow diagram are as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Raw Message: ****Hello Developers!
Hash of Raw Message: 0x8a67fef1b0a61b7d4e8f0921c7c93372ab0e38f1317b2e9431cdca324c041792
Eth-Signed Message: 0x21d8c6f7bbaa104e61dfba68f68eabdfe47968b3f9b3fea6d9146214743cb01d
Signature: 0xa01b7764293ccab794ef74b7d3d21f88f62eeac7acc2959c422d254a3aadb60f08f7c4afd25b088af870772d20df8482d85f0b675441bbe61474d75c5c2663761b
Signer: ****0xcDb333BCE61C1E4a3Da9F4a2831e23b155f3949B
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can use the above smart contract to verify this details. Paste the contract into &lt;a href="https://remix.ethereum.org/#optimize=false&amp;amp;runs=200&amp;amp;evmVersion=null&amp;amp;version=soljson-v0.8.7+commit.e28d00a7.js" rel="noopener noreferrer"&gt;Remix&lt;/a&gt; and deploy it to the &lt;code&gt;Javascript VM&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To start with, we can use the &lt;code&gt;verify&lt;/code&gt; function passing in the &lt;em&gt;Raw Message&lt;/em&gt; and &lt;em&gt;Signature&lt;/em&gt; to obtain the signing account. We can then verify manually that the returned signer is the correct account signing the message.&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%2Fi65pv9bfnj0kefmx0051.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%2Fi65pv9bfnj0kefmx0051.png" alt="Verification Example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Similarly, we can also use the other functions to calculate the other values specified in the flow diagram. We will again use this contract after we have completed our app but for now, let's back to our main objective of app development.&lt;/p&gt;

&lt;h2&gt;
  
  
  Developing the App
&lt;/h2&gt;

&lt;p&gt;If you want to continue with your code, that is highly encouraged, however, if you want to have a common starting point with this tutorial, clone &lt;a href="https://github.com/BhaskarDutta2209/FlutterAppWithMetamask" rel="noopener noreferrer"&gt;this&lt;/a&gt; repo and create a new branch, called &lt;code&gt;signing-message&lt;/code&gt; from the &lt;code&gt;login-with-metamask&lt;/code&gt; branch.&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/BhaskarDutta2209/FlutterAppWithMetamask
&lt;span class="nb"&gt;cd &lt;/span&gt;FlutterAppWithMetamask
git checkout login-with-metamask
git checkout &lt;span class="nt"&gt;-b&lt;/span&gt; signing-message
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open the project folder in your code editor of choice and we are &lt;em&gt;Ready To Go!&lt;/em&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Installing dependencies
&lt;/h3&gt;

&lt;p&gt;For this tutorial, we will be using &lt;code&gt;keccak256&lt;/code&gt; for hashing our message. For doing so, we will need the &lt;a href="https://pub.dev/packages/web3dart" rel="noopener noreferrer"&gt;web3dart&lt;/a&gt; package. For this blog we will be limiting ourselves to only the &lt;a href="https://pub.dev/documentation/web3dart/latest/crypto/crypto-library.html" rel="noopener noreferrer"&gt;crypto&lt;/a&gt; library, however, in future blogs, this same package will also be used for interacting with the smart contracts. To add the package, 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;flutter pub add web3dart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Creating a  function for signing message
&lt;/h3&gt;

&lt;p&gt;Open the &lt;code&gt;login_page.dart&lt;/code&gt; file inside the &lt;code&gt;_LoginPageState&lt;/code&gt; class where we have previously defined &lt;code&gt;_session&lt;/code&gt; and &lt;code&gt;_uri&lt;/code&gt; variables, define a new variable called &lt;code&gt;_signature&lt;/code&gt; for storing the signed data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="n"&gt;_session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_uri&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_signature&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now inside the same class we define a new function called &lt;code&gt;signMessageWithMetamask&lt;/code&gt; as shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;signMessageWithMetamask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Besides the &lt;code&gt;BuildContext&lt;/code&gt;, this function takes in a &lt;code&gt;String&lt;/code&gt; parameter that represents the message to be signed. In the later section of this blog, we will see that the &lt;code&gt;message&lt;/code&gt; is nothing but the &lt;code&gt;keccak256&lt;/code&gt; hash of the data we want to be signed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Writing the function body
&lt;/h3&gt;

&lt;p&gt;The main content of the function body is as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;signMessageWithMetamask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;connector&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;connected&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Message received"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="n"&gt;EthereumWalletConnectProvider&lt;/span&gt; &lt;span class="n"&gt;provider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
          &lt;span class="n"&gt;EthereumWalletConnectProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;connector&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="n"&gt;launchUrlString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_uri&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;mode:&lt;/span&gt; &lt;span class="n"&gt;LaunchMode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;externalApplication&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="n"&gt;signature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;provider&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;personalSign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nl"&gt;message:&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;address:&lt;/span&gt; &lt;span class="n"&gt;_session&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&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="nl"&gt;password:&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="n"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_signature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error while signing transaction"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we are doing the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First, we check whether we are already connected with an external wallet using the &lt;code&gt;connect&lt;/code&gt; variable defined in the previous tutorial.&lt;/li&gt;
&lt;li&gt;If we are connected, we proceed with signing our message. We are using &lt;code&gt;try-catch&lt;/code&gt; block for error handling and are printing the error to the console. In a production-ready app, we should properly notify the user about any caused error. The most common cause where an error can be generated is if the user rejects signing the message, after the metamask popup.&lt;/li&gt;
&lt;li&gt;Before signing the message, we must define a &lt;code&gt;provider&lt;/code&gt;. This step may seem familiar if you have used &lt;code&gt;web3.js&lt;/code&gt; or &lt;code&gt;ethers.js&lt;/code&gt; before. Since our targeted blockchain is &lt;code&gt;Polygon&lt;/code&gt;, which is a fork of the &lt;code&gt;Ethereum&lt;/code&gt; blockchain network, the provider type is &lt;code&gt;EthereumWalletConnectProvider&lt;/code&gt; and we pass the &lt;code&gt;connector&lt;/code&gt; as an argument.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;We want the Metamask app to pop up for signing the message. To open the Metamask app, we use the &lt;code&gt;launchUrlString&lt;/code&gt; function passing in the &lt;code&gt;_uri&lt;/code&gt;. This is similar to how we opened Metamask during login.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Note:&lt;/em&gt;&lt;/strong&gt; Here we are not using &lt;code&gt;await&lt;/code&gt; keyword, because we want to open Metamask and continue with the rest of our function execution and not wait for Metamask to close. After a user signs the message, metamask will close automatically.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Now we use the &lt;code&gt;personalSign&lt;/code&gt; method in the &lt;code&gt;provider&lt;/code&gt; object defined for signing the message passed as a function parameter. This method also takes the signing account as a parameter. We use &lt;code&gt;_seesion.accounts[0]&lt;/code&gt; to pass the current metamask account connected with the app.&lt;/p&gt;

&lt;p&gt;Here we are using &lt;code&gt;await&lt;/code&gt; keyword because we want the function execution to wait until the user signs the data.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finally, we use &lt;code&gt;setState&lt;/code&gt; method to update the value of &lt;code&gt;_signature&lt;/code&gt; variable with the latest obtained signature. Using the &lt;code&gt;setState&lt;/code&gt; function will also re-render the app screen and will display the updated information.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Adding the button
&lt;/h3&gt;

&lt;p&gt;We want to add a simple &lt;code&gt;Sign Message&lt;/code&gt; button before the &lt;code&gt;Slide to login&lt;/code&gt; slider. For showing the button we will use a similar &lt;code&gt;ternary-operator&lt;/code&gt; syntax used in our previous tutorial. We check whether the &lt;code&gt;_signature&lt;/code&gt; variable is &lt;code&gt;null&lt;/code&gt; as a &lt;code&gt;null&lt;/code&gt; value would signify that the message is not signed. If the value of &lt;code&gt;_signature&lt;/code&gt; is set, aka the message is signed by the user, we display the signature on the app screen. &lt;/p&gt;

&lt;p&gt;Inside our &lt;code&gt;login_page.dart&lt;/code&gt; file, we replace the &lt;code&gt;SliderButton()&lt;/code&gt; section with the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_signature&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;Container&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;alignment:&lt;/span&gt; &lt;span class="n"&gt;Alignment&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;center&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;ElevatedButton&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nl"&gt;onPressed:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="n"&gt;signMessageWithMetamask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;generateSessionMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
              &lt;span class="n"&gt;_session&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&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="nl"&gt;child:&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Sign Message'&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;crossAxisAlignment:&lt;/span&gt;
        &lt;span class="n"&gt;CrossAxisAlignment&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;center&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nl"&gt;children:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="n"&gt;Row&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nl"&gt;children:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
              &lt;span class="s"&gt;"Signature: "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="nl"&gt;style:&lt;/span&gt; &lt;span class="n"&gt;GoogleFonts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;merriweather&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="nl"&gt;fontWeight:&lt;/span&gt; &lt;span class="n"&gt;FontWeight&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;bold&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="nl"&gt;fontSize:&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
              &lt;span class="n"&gt;truncateString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;_signature&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toString&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="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
              &lt;span class="nl"&gt;style:&lt;/span&gt; &lt;span class="n"&gt;GoogleFonts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;inconsolata&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="nl"&gt;fontSize:&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
          &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;SizedBox&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;height:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;SliderButton&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nl"&gt;action:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// TODO: Navigate to main page&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="nl"&gt;label:&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Slide to login'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="nl"&gt;icon:&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Icon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Icons&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;check&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sorry for the mess that this Dart code is, but if you look closely into the code, it only does the following things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If the value of &lt;code&gt;_signature&lt;/code&gt; is &lt;code&gt;null&lt;/code&gt;, we create an &lt;code&gt;ElevatedButton&lt;/code&gt; with the text &lt;code&gt;Sign Message&lt;/code&gt;. On clicking this button, the &lt;code&gt;signMessageWithMetamask&lt;/code&gt; function is called passing in the current context and the message to be signed as a parameter. To obtain the message to be signed we are using the &lt;code&gt;generateSessionMessage&lt;/code&gt; function that takes in the currently connected account as a parameter. We will define this function in the next section.&lt;/li&gt;
&lt;li&gt;If the value of &lt;code&gt;_signature&lt;/code&gt; is not &lt;code&gt;null&lt;/code&gt;, we show the signature on the app screen. Since the signature is a very long string, we use a function called &lt;code&gt;truncateString&lt;/code&gt; to truncate it in the &lt;code&gt;AAAA…BB&lt;/code&gt; format. We will define this function also in the next section.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Creating the helper functions
&lt;/h3&gt;

&lt;p&gt;Inside the &lt;code&gt;utils&lt;/code&gt; folder, we create a new file named &lt;code&gt;helperfunctions.dart&lt;/code&gt;. In this file, we will specify the two helper functions used above. We start with the &lt;code&gt;truncateString&lt;/code&gt; function, which is the easier of the two to implement.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;truncateString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;front&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;front&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;finalString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${text.substring(0, front)}&lt;/span&gt;&lt;span class="s"&gt;...&lt;/span&gt;&lt;span class="si"&gt;${text.substring(text.length - end)}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;finalString&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="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this function:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;front&lt;/code&gt; and &lt;code&gt;end&lt;/code&gt; represent the number of characters to be displayed before and after the truncation symbol (&lt;code&gt;…&lt;/code&gt;) respectively.&lt;/li&gt;
&lt;li&gt;We check if it’s possible to truncate the string based on the passed parameters, i.e. the passed &lt;code&gt;text&lt;/code&gt; has a length greater than &lt;code&gt;front&lt;/code&gt; + &lt;code&gt;end&lt;/code&gt;. If so, we use the &lt;code&gt;substring&lt;/code&gt; method to truncate the string to our requirement.&lt;/li&gt;
&lt;li&gt;Finally, we return the truncated string or the original string if truncating is not possible.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now we define the &lt;code&gt;generateSessionMessage&lt;/code&gt; function. Since in this function we will need to implement &lt;code&gt;keccak256&lt;/code&gt; hashing, we import the &lt;code&gt;web3dart/crypto.dart&lt;/code&gt; package by adding the following line at the top of our script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:web3dart/crypto.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will give us access to a function called &lt;code&gt;keccak256Utf8&lt;/code&gt; which uses the keccak256 hashing algorithm. This will return the data in form of an array of &lt;code&gt;bytes&lt;/code&gt;. We will then use another function called &lt;code&gt;bytesToHex&lt;/code&gt; to convert this array to hexadecimal string format. We prefix &lt;code&gt;“0x”&lt;/code&gt; with the generated string to denote that the string is in hexadecimal format. For simplicity, we have initialized the raw message as a string containing the account address of the user. However, it is possible and encouraged to use a more complex data structure for the raw message e.g. serialized JSON. The complete function looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;generateSessionMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;accountAddress&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'Hello &lt;/span&gt;&lt;span class="si"&gt;$accountAddress&lt;/span&gt;&lt;span class="s"&gt;, welcome to our app. By signing this message you agree to learn and have fun with blockchain'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="n"&gt;hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;keccakUtf8&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;hashString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'0x&lt;/span&gt;&lt;span class="si"&gt;${bytesToHex(hash).toString()}&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;hashString&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we import our helper functions in our &lt;code&gt;login_page.dart&lt;/code&gt; file using the following import statement:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:my_app/utils/helperfunctions.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Running our app
&lt;/h2&gt;

&lt;p&gt;Finally, we are ready to run our app 🤞🏾🤞🏾🤞🏾!&lt;/p&gt;

&lt;p&gt;If everything was done correctly, on running the app, we will be presented with a flow similar to our previous tutorial. However, when we are connected with the correct network, we will be presented with an additional &lt;code&gt;“Sign Message”&lt;/code&gt; button. On clicking on it, we are treated with a Metamask popup that looks something like the following:&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%2Fzmg8q6atz020juddi1qt.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%2Fzmg8q6atz020juddi1qt.png" alt="Sign message popup"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here you can notice one of the challenges of using the Metamask app, that is the message shown is not human readable. Due to some internal bug in the app, the message section is not able to show the hexadecimal hash properly.&lt;/p&gt;

&lt;p&gt;Nevertheless, when we click on the &lt;code&gt;Sign&lt;/code&gt; button, we are returned to our app screen. Now we can see the truncated version of the signature along with our old &lt;code&gt;Slide to login&lt;/code&gt; slider.&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%2Fuyj4sgfys6mt3ung12l8.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%2Fuyj4sgfys6mt3ung12l8.png" alt="Details in App Screen"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can get the complete signature from the console. In my case the details are as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Account: 0x11Ea3D9B50116986C77E17Fa177D56fae0b73631
Signature: 0xd4e8b7997d5e244981965a5f301658f780242ff51226e0fc6af21564867a0d560292b1aa17e41ca836111b7413bbbd3a0a430c0715ae511dd206396c8bed7abe1b
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Verifying the signature using a smart contract
&lt;/h3&gt;

&lt;p&gt;Now we get back to our smart contract and try to verify this signature. Depending on the account you used, the message and the signature will be different. In my case:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Message: "Hello 0x11ea3d9b50116986c77e17fa177d56fae0b73631, welcome to our app. By signing this message you agree to learn and have fun with blockchain"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We call the &lt;code&gt;verifySignature&lt;/code&gt; function with the above parameters to obtain the signing account.&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%2Fhh6fpswc7vcud2a3zyce.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%2Fhh6fpswc7vcud2a3zyce.png" alt="Verify"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can cross-check the returned address with the address used for signing. This proves that by using the signature we can determine the account that provided the signature. &lt;strong&gt;&lt;em&gt;Mission Accomplished&lt;/em&gt;&lt;/strong&gt; 😎🎉!&lt;/p&gt;

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

&lt;p&gt;In this tutorial, we learned about signing messages using Ethereum wallets like Metamask. We also learned how we can use Metamask in a Flutter app for generating the signature of a &lt;code&gt;String&lt;/code&gt; message. Finally, we verified our signature using a simple smart contract.&lt;/p&gt;

&lt;p&gt;The code for this project is uploaded to Github &lt;a href="https://github.com/BhaskarDutta2209/FlutterAppWithMetamask" rel="noopener noreferrer"&gt;here&lt;/a&gt;. The updated code for this tutorial will be present in the &lt;code&gt;signing-message&lt;/code&gt; branch.&lt;/p&gt;

&lt;h2&gt;
  
  
  About me
&lt;/h2&gt;

&lt;p&gt;I am working in the domain of blockchain technology for more than 2years now. I aspire to learn new technologies targeted at solving real-world problems and write tutorials with unique approaches. Kindly follow me to stay updated as I write new tutorials and show you support through reactions and comments.&lt;/p&gt;

&lt;p&gt;I am also looking forward to writing sponsored articles and creating YouTube videos based on my articles. If you want to connect with me or provide your feedback, you can find me on &lt;a href="https://www.linkedin.com/in/itsbhaskardutta/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;, &lt;a href="https://twitter.com/Bhaskar2209" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;, or through my &lt;a href="//mailto:bhaskar@bhaskardutta.tech"&gt;mail&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We will meet again with another new tutorial or blog, till then stay safe, spend time with your family and &lt;strong&gt;&lt;em&gt;KEEP BUIDLING!&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>blockchain</category>
      <category>tutorial</category>
      <category>metamask</category>
    </item>
    <item>
      <title>Building with Flutter and Metamask</title>
      <dc:creator>Bhaskar </dc:creator>
      <pubDate>Sat, 04 Jun 2022 20:59:22 +0000</pubDate>
      <link>https://dev.to/bhaskardutta/building-with-flutter-and-metamask-8h5</link>
      <guid>https://dev.to/bhaskardutta/building-with-flutter-and-metamask-8h5</guid>
      <description>&lt;p&gt;Building apps is one of the coolest things to be done as a software developer and tech enthusiast.  Apps are not only more portable and user friendly, based on the requirements, but sometimes they are the only option for a particular application In this tutorial and the upcoming series, we will learn how to build a cool cross-platform mobile application using &lt;strong&gt;Flutter&lt;/strong&gt; and &lt;strong&gt;Metamask&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem we are solving
&lt;/h2&gt;

&lt;p&gt;To interact with the blockchain, the users must have an account (public and private key pair) on the blockchain that is used to sign the transactions. Sharing the private key with someone is equivalent to sharing access to the account. Because of this, users will be reluctant to provide their private key to the app since this would raise a lot of security concerns. The industry-trusted method is to use a “Non-custodial wallet” like &lt;a href="https://metamask.io/" rel="noopener noreferrer"&gt;Metamask&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Although there are numerous tutorials on how to use the browser extension of Metamask, using the mobile app version isn’t properly documented yet. In this tutorial series, we will be covering how to connect a Flutter App with Metamask for user login and in later articles, interacting with smart contracts will also be covered. We are using &lt;a href="https://flutter.dev/" rel="noopener noreferrer"&gt;Flutter&lt;/a&gt; as our development framework of choice because we want to build a cross-platform application that is supported in both Android and IOS.&lt;/p&gt;

&lt;p&gt;In this tutorial, we will be building an App that will be using Metamask for login. It will get the public key from Metamask. Metamask can also be used for signing messages and transactions but that will be covered in a different tutorial. The following GIF shows what we are going to build:&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%2Foatwqsu074b76lci0652.gif" 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%2Foatwqsu074b76lci0652.gif" alt="Demo GIF" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Pre-requisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Flutter is installed in your system.  You can follow the official guide of Flutter &lt;a href="https://docs.flutter.dev/get-started/install" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Have an Android / Ios emulator or physical device connected that will be used for testing the application. I recommend using Android Emulator as there are some bugs while working with Ios.&lt;/li&gt;
&lt;li&gt;Install and set up &lt;a href="https://play.google.com/store/apps/details?id=io.metamask&amp;amp;hl=en_IN&amp;amp;gl=US" rel="noopener noreferrer"&gt;Metamask Mobile App&lt;/a&gt; in your Android emulator.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;💡 It is recommended to use &lt;a href="https://code.visualstudio.com/" rel="noopener noreferrer"&gt;VS Code&lt;/a&gt; with &lt;a href="https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter" rel="noopener noreferrer"&gt;Flutter&lt;/a&gt; extension.&lt;/p&gt;

&lt;h2&gt;
  
  
  Known challenges
&lt;/h2&gt;

&lt;p&gt;While writing this article, there are some challenges with building and running the app on IoS.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;IoS doesn’t support installing third-party applications from App Store for simulators. So we have to install Metamask directly from its &lt;a href="https://github.com/MetaMask/metamask-mobile" rel="noopener noreferrer"&gt;Github repo&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;If you are using a MacBook with Apple Silicon, there are some extra steps needed for setting up Metamask in a simulator. You can read about it here.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://medium.com/wolox/ios-deep-linking-url-scheme-vs-universal-links-50abd3802f97" rel="noopener noreferrer"&gt;Deep Linking&lt;/a&gt; with Metamask is not working as expected. (For this tutorial it is recommended to use Android Emulator)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I will update this article if I find the solutions to the above problems. Till then your helpful comments are highly expected.&lt;/p&gt;

&lt;h2&gt;
  
  
  Project initiation
&lt;/h2&gt;

&lt;p&gt;We start by running &lt;code&gt;flutter doctor&lt;/code&gt; to make sure we have everything set up properly for our development journey. You should see similar to :&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%2Fp84go1ylipc8160zkjfk.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%2Fp84go1ylipc8160zkjfk.png" alt="Running Flutter Doctor" width="800" height="254"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we start by creating a new flutter project. To do this, open the location where you want to store your project folder in your terminal and 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;flutter create my_app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here &lt;code&gt;my_app&lt;/code&gt; is the name of the project we are going to build. This will create a folder with the same name where all our code will reside. You should see an output similar to:&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%2Fgswalntyn86lp7p6adny.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%2Fgswalntyn86lp7p6adny.png" alt="Flutter initiation" width="800" height="284"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Open this folder in a code editor of your choice.  You can run your app by typing &lt;code&gt;flutter run&lt;/code&gt; or using the &lt;em&gt;Flutter Debugger&lt;/em&gt; if you are using VS Code. &lt;/p&gt;

&lt;h3&gt;
  
  
  Installing dependencies
&lt;/h3&gt;

&lt;p&gt;For this project we will require the following dependencies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://pub.dev/packages/url_launcher" rel="noopener noreferrer"&gt;url_launcher:&lt;/a&gt;&lt;/strong&gt; This will be used for opening &lt;code&gt;Metamask&lt;/code&gt; from our app using a URI.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://pub.dev/packages/walletconnect_dart" rel="noopener noreferrer"&gt;walletconnect_dart:&lt;/a&gt; This will be used for generating a URI that will be used to launch Metamask.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://pub.dev/packages/google_fonts" rel="noopener noreferrer"&gt;google_fonts:&lt;/a&gt; Optional dependency for using Google Fonts in our app.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://pub.dev/packages/slider_button" rel="noopener noreferrer"&gt;slider_button:&lt;/a&gt; Optional dependency for using a Slider Button for login purposes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To install these dependencies, type in 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;flutter pub add url_launcher walletconnect_dart google_fonts slider_button
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Adding assets folder
&lt;/h3&gt;

&lt;p&gt;We want to use static images in our app’s UI. For that, we have to create a folder that will contain our assets and tell flutter to use them as assets for our project. &lt;/p&gt;

&lt;p&gt;Create a folder called &lt;code&gt;assets&lt;/code&gt; inside the root &lt;code&gt;my_app&lt;/code&gt; folder. The name of the root folder will be whatever name you used for creating the flutter project. Inside the &lt;code&gt;assets&lt;/code&gt; folder, we will create an &lt;code&gt;images&lt;/code&gt; folder for storing our image assets. Finally, inside the &lt;code&gt;pubspec.yaml&lt;/code&gt; file we add this folder by adding the following lines in the &lt;code&gt;flutter&lt;/code&gt; section:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;flutter&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="c1"&gt;# The following line ensures that the Material Icons font is&lt;/span&gt;
  &lt;span class="c1"&gt;# included with your application, so that you can use the icons in&lt;/span&gt;
  &lt;span class="c1"&gt;# the material Icons class.&lt;/span&gt;
  &lt;span class="na"&gt;uses-material-design&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

  &lt;span class="c1"&gt;# To add assets to your application, add an assets section, like this:&lt;/span&gt;
  &lt;span class="na"&gt;assets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;assets/images/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Understanding the flow
&lt;/h3&gt;

&lt;p&gt;Finally, before we start coding our app, it is important to understand the user flow. The following diagram represents the flow a user will go through starting from when he opens our app:&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%2Fyaafygrtugvirggejee8.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%2Fyaafygrtugvirggejee8.png" alt="Flow diagram" width="800" height="357"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Code Along
&lt;/h2&gt;

&lt;p&gt;We will start from the &lt;code&gt;main.dart&lt;/code&gt; inside the &lt;code&gt;lib&lt;/code&gt; folder. The &lt;code&gt;main.dart&lt;/code&gt; is the first file to be compiled and executed by Flutter. Clear all the contents of this file and paste in the following lines of code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:flutter/material.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;runApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;MyApp&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyApp&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;StatelessWidget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;MyApp&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;key:&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&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="n"&gt;MaterialApp&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We start by creating a new Stateless Widget. This widget will act as the starting point of our project. Based on the flow diagram shown above, the first thing to do will be to create the Login Page. Although for this tutorial our app will have only one page, we should have a proper routing system so that we can easily keep on adding newer pages as we proceed with our project.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating routes
&lt;/h3&gt;

&lt;p&gt;The way routing works in flutter is quite similar to how it works for web apps, i.e. using the &lt;code&gt;/path&lt;/code&gt; format. In simple words, routes are nothing but a mapping of a path to its respective widget. An example of how routes work is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;MaterialApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nl"&gt;initialRoute:&lt;/span&gt; &lt;span class="s"&gt;"/login"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nl"&gt;routes:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s"&gt;"/login"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;LoginPage&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
          &lt;span class="s"&gt;"/home"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;HomePage&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;Inside &lt;code&gt;routes&lt;/code&gt; we define all the routes that will be used in our project and their respective widgets. In this example we are saying that the widget &lt;code&gt;LoginPage&lt;/code&gt; will be rendered when the user is in the &lt;code&gt;/login&lt;/code&gt; router and similarly when the user is in the &lt;code&gt;/home&lt;/code&gt; route, the &lt;code&gt;HomePage&lt;/code&gt; widget will be rendered. The &lt;code&gt;initialRoute&lt;/code&gt; field tells the initial or starting route to be loaded. In this example, the first widget the user sees on opening the app will be the &lt;code&gt;LoginPage&lt;/code&gt; widget.&lt;/p&gt;

&lt;p&gt;Since there will be multiple routes present in a project which are used across multiple files, it is not wise to directly type the route. Rather, one should have constant variable names defined for the code to be more robust. For this create a new folder called &lt;code&gt;utils&lt;/code&gt; inside the &lt;code&gt;lib&lt;/code&gt; folder and inside the &lt;code&gt;utils&lt;/code&gt; folder create a new file called &lt;code&gt;routes.dart&lt;/code&gt;. This file will store all our routes. Inside this file define the routes like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyRoutes&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;loginRoute&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'/login'&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 let’s get back to our &lt;code&gt;main.dart&lt;/code&gt; file and make the following changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:flutter/material.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:my_app/utils/routes.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;runApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;MyApp&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyApp&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;StatelessWidget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;MyApp&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;key:&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&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="n"&gt;MaterialApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;initialRoute:&lt;/span&gt; &lt;span class="n"&gt;MyRoutes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;loginRoute&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nl"&gt;routes:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;MyRoutes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;loginRoute&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;LoginPage&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we are importing our newly created &lt;code&gt;routes.dart&lt;/code&gt; file and using the variable name instead of directly typing the route. Since we don’t have the &lt;code&gt;LoginPage&lt;/code&gt; widget yet, we will be getting an error message. So let’s create our login page.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating Login Page
&lt;/h3&gt;

&lt;p&gt;Inside the &lt;code&gt;lib&lt;/code&gt; folder, let’s create a new folder called &lt;code&gt;pages&lt;/code&gt; that will have all our pages. This folder will have all our pages. Inside the &lt;code&gt;pages&lt;/code&gt; folder, create a new file called &lt;code&gt;login_page.dart&lt;/code&gt;. Inside this file paste in the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:flutter/material.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LoginPage&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;StatefulWidget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;LoginPage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;key:&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;LoginPage&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;createState&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_LoginPageState&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;_LoginPageState&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;LoginPage&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&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="n"&gt;Scaffold&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we are creating a new Stateful Widget called &lt;code&gt;LoginPage&lt;/code&gt;. Now we can import this into our &lt;code&gt;main.dart&lt;/code&gt; file by adding &lt;code&gt;import 'package:my_app/pages/login_page.dart';&lt;/code&gt; at the start of the file. The final main.dart file looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:flutter/material.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:my_app/utils/routes.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:my_app/pages/login_page.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;runApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;MyApp&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyApp&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;StatelessWidget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;MyApp&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;key:&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&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="n"&gt;MaterialApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;initialRoute:&lt;/span&gt; &lt;span class="n"&gt;MyRoutes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;loginRoute&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nl"&gt;routes:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;MyRoutes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;loginRoute&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;LoginPage&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Designing the Login Page
&lt;/h3&gt;

&lt;p&gt;Now it’s time to design our Login Page. For this tutorial, we will be designing a very simple Login Page. To start with, it only has an image along with &lt;code&gt;Connect with Metamask&lt;/code&gt; button. When Metamask is connected, it will display the account address and the chain connected with it. If the chain is not the officially supported chain (Mumbai Testnet for our case), we display a warning asking the users to connect to the appropriate chain. Finally, if the user is connected with the connected network, we show the details along with a “Slide to login” slider. These three are shown in the following diagrams respectively:&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%2Fx6u9s73ds2y15q79ncbl.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%2Fx6u9s73ds2y15q79ncbl.png" alt="App Screens" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Building the default Login Page
&lt;/h3&gt;

&lt;p&gt;We start by editing the &lt;code&gt;login_page.dart&lt;/code&gt; file. Make the following changes inside the &lt;code&gt;_LoginPageState&lt;/code&gt; class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;_LoginPageState&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;LoginPage&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&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="n"&gt;Scaffold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;appBar:&lt;/span&gt; &lt;span class="n"&gt;AppBar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nl"&gt;title:&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Login Page'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="nl"&gt;body:&lt;/span&gt; &lt;span class="n"&gt;SingleChildScrollView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nl"&gt;mainAxisAlignment:&lt;/span&gt; &lt;span class="n"&gt;MainAxisAlignment&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;center&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nl"&gt;children:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
              &lt;span class="s"&gt;'assets/images/main_page_image.png'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="nl"&gt;fit:&lt;/span&gt; &lt;span class="n"&gt;BoxFit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fitHeight&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;ElevatedButton&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="nl"&gt;onPressed:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Connect with Metamask"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
          &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we are doing the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We start by returning a &lt;code&gt;Scaffold&lt;/code&gt;. &lt;code&gt;Scaffold&lt;/code&gt; in flutter is used to implement the basic material design layout. You can read more about it &lt;a href="https://api.flutter.dev/flutter/material/Scaffold-class.html" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Then we are defining an &lt;code&gt;AppBar&lt;/code&gt; with the title “Login Page”. This will be the title to be displayed on top of our app.&lt;/li&gt;
&lt;li&gt;We start the body of our app by defining a &lt;code&gt;SingleChildScrollView&lt;/code&gt;. This is helpful when our App is opened on a phone with a relatively smaller display. It enables the users to scroll through our widget. Read more about it &lt;a href="https://api.flutter.dev/flutter/widgets/SingleChildScrollView-class.html" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Inside the &lt;code&gt;SingleChildScrollView&lt;/code&gt; we define a &lt;code&gt;Column&lt;/code&gt; to contain the various components of our page as its &lt;code&gt;children&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The first child we define is an image. We want to render an image stored inside our &lt;code&gt;assets&lt;/code&gt; folder. For this, we use &lt;code&gt;Image.asset()&lt;/code&gt; and pass in the path to where the image is stored. Remember to use a path already added as a source of assets. Previously we added the &lt;code&gt;assets/images/&lt;/code&gt; as a source of assets. I am using &lt;a href="https://pbs.twimg.com/card_img/1529204914425061376/Q6EAQTO3?format=png&amp;amp;name=small" rel="noopener noreferrer"&gt;this&lt;/a&gt; image that I downloaded into the &lt;code&gt;images&lt;/code&gt; folder and named &lt;code&gt;main_page_image.png&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Next, we create a button using the &lt;code&gt;ElevatedButton&lt;/code&gt; class. It takes two arguments:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;onPressed&lt;/code&gt;: The function to be executed when the button is clicked. For now, this is blank.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;child&lt;/code&gt;: A child widget that will determine how our button will look. For now, it is a &lt;code&gt;Text&lt;/code&gt; with the string &lt;code&gt;“Connect with Metamask”&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;If you run the app now, you should see something like:&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%2F9l8nqllyt6u41mzk54jf.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%2F9l8nqllyt6u41mzk54jf.png" alt="Initial look" width="690" height="1494"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Although pressing the button doesn’t do anything right now, we have our default look ready. It only gets more interesting from here 😎😎😎.&lt;/p&gt;

&lt;h3&gt;
  
  
  Understanding the dependencies
&lt;/h3&gt;

&lt;p&gt;Next, we will be writing the logic behind the “Connect with Metamask” button. For these we will be using two important dependencies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;walletconnect_dart&lt;/code&gt;: This dependency will be used for connecting with Metamask. Practically it can be used with other wallets like Trust Wallet as well, but for this tutorial, we will focus only on Metamask.&lt;/p&gt;

&lt;p&gt;To understand how this works, we must first understand how &lt;a href="https://walletconnect.com/" rel="noopener noreferrer"&gt;Wallet Connect&lt;/a&gt; works. Wallet Connect is a popularly used protocol for connecting web apps with mobile wallets (commonly by scanning a QR code). It generates a URI that is used by the mobile app for securely signing transactions over a remote connection. The way our app works is, that we directly open the URI in Metamask using our next dependency.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;walletconnect_dart&lt;/code&gt; is a package for flutter written in &lt;code&gt;dart&lt;/code&gt; programming language. We will use this dependency to generate our URI and connect with Metamask. This package also provides us with callback functions that can be used to listen to any changes done in Metamask, like changing the network connected with.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;url_launcher&lt;/code&gt;: This dependency is used for launching URLs in android and ios. We will be using this dependency for launching the URI generated by &lt;code&gt;walletconnect_dart&lt;/code&gt; in the Metamask app.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Using the dependencies in our code
&lt;/h3&gt;

&lt;p&gt;We start by importing the dependencies in our &lt;code&gt;login_page.dart&lt;/code&gt; file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:walletconnect_dart/walletconnect_dart.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:url_launcher/url_launcher_string.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, inside our &lt;code&gt;_LoginPageState&lt;/code&gt; class we define a connector that will be used to connect with Metamask&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="n"&gt;connector&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;WalletConnect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nl"&gt;bridge:&lt;/span&gt; &lt;span class="s"&gt;'https://bridge.walletconnect.org'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;clientMeta:&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;PeerMeta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nl"&gt;name:&lt;/span&gt; &lt;span class="s"&gt;'My App'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nl"&gt;description:&lt;/span&gt; &lt;span class="s"&gt;'An app for converting pictures to NFT'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nl"&gt;url:&lt;/span&gt; &lt;span class="s"&gt;'https://walletconnect.org'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nl"&gt;icons:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="s"&gt;'https://files.gitbook.com/v0/b/gitbook-legacy-files/o/spaces%2F-LJJeCjcLrr53DcT1Ml7%2Favatar.png?alt=media'&lt;/span&gt;
    &lt;span class="p"&gt;]));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are using the &lt;code&gt;WalletConnect&lt;/code&gt; class to define our connector. It takes in the following arguments:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;bridge&lt;/code&gt;: Link to the Wallet Connect bridge&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;clientMeta&lt;/code&gt;: This contains optional metadata about the client

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;name&lt;/code&gt;: Name of the application&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;description&lt;/code&gt;: A small description of the application&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;url&lt;/code&gt;: Url of the website&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;icon&lt;/code&gt;: The icon to be shown in the Metamask connection pop-up&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;We also define two variables called &lt;code&gt;_session&lt;/code&gt; and &lt;code&gt;_uri&lt;/code&gt;, which will be used to store the session and URI respectively when our widget state is updated.&lt;/p&gt;

&lt;p&gt;We define a function called &lt;code&gt;loginUsingMetamask&lt;/code&gt; to handle the login process as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;loginUsingMetamask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;connector&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;connected&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;connector&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;createSession&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;onDisplayUri:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_uri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;launchUrlString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;mode:&lt;/span&gt; &lt;span class="n"&gt;LaunchMode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;externalApplication&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
       &lt;span class="p"&gt;});&lt;/span&gt;
             &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&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="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;chainId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
       &lt;span class="n"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="n"&gt;_session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
       &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we are doing the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First, we check if the connection is already established by checking the value of &lt;code&gt;connector.connected&lt;/code&gt; variable. If the connection is not already established, we proceed with the code inside the &lt;code&gt;if&lt;/code&gt; block.&lt;/li&gt;
&lt;li&gt;We use &lt;code&gt;try-catch&lt;/code&gt; block to catch any exception that may arise during establishing the connection, like the user clicking on &lt;code&gt;cancel&lt;/code&gt; in the Metamask pop-up.&lt;/li&gt;
&lt;li&gt;Inside the &lt;code&gt;try&lt;/code&gt; block, we create a new session by using the &lt;code&gt;connector.createSession()&lt;/code&gt; function. It takes in a function as an argument that is executed when the URI is generated. Inside this function, we use the &lt;code&gt;launchUrlString()&lt;/code&gt; function to open the generated URI in an external app. We pass in the generated URI as a parameter and since it will be opening an external application, we set the &lt;code&gt;mode&lt;/code&gt; as &lt;code&gt;LaunchMode.externalApplication&lt;/code&gt;. Finally, since we want our code to wait until the connection is confirmed using Metamask, we use the &lt;code&gt;await&lt;/code&gt; keyword with &lt;code&gt;launchUrlString()&lt;/code&gt; function.&lt;/li&gt;
&lt;li&gt;We can fetch the accounts connected by using &lt;code&gt;session.accounts&lt;/code&gt; and the chain id by using &lt;code&gt;session.chainId&lt;/code&gt;. For now, we print the selected account using &lt;code&gt;session.accounts[0]&lt;/code&gt; and the chain Id to the console to check if our code is working properly.&lt;/li&gt;
&lt;li&gt;Finally, we update the state of our app using &lt;code&gt;setState&lt;/code&gt; and store the created session in the &lt;code&gt;_session&lt;/code&gt; variable.&lt;/li&gt;
&lt;li&gt;If any exception is generated in any of the above statements, the &lt;code&gt;catch&lt;/code&gt; block will be executed. Right now we only print the generated exception, but in the latter stages of the project, we can use more robust exception handling.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finally, we call the &lt;code&gt;loginUsingMetamask&lt;/code&gt; function as the &lt;code&gt;onPressed&lt;/code&gt; argument of our created button. The final code looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:flutter/material.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:walletconnect_dart/walletconnect_dart.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:url_launcher/url_launcher_string.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LoginPage&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;StatefulWidget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;LoginPage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;key:&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;LoginPage&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;createState&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_LoginPageState&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;_LoginPageState&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;LoginPage&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="n"&gt;connector&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;WalletConnect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;bridge:&lt;/span&gt; &lt;span class="s"&gt;'https://bridge.walletconnect.org'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nl"&gt;clientMeta:&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;PeerMeta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nl"&gt;name:&lt;/span&gt; &lt;span class="s"&gt;'My App'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nl"&gt;description:&lt;/span&gt; &lt;span class="s"&gt;'An app for converting pictures to NFT'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nl"&gt;url:&lt;/span&gt; &lt;span class="s"&gt;'https://walletconnect.org'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nl"&gt;icons:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s"&gt;'https://files.gitbook.com/v0/b/gitbook-legacy-files/o/spaces%2F-LJJeCjcLrr53DcT1Ml7%2Favatar.png?alt=media'&lt;/span&gt;
          &lt;span class="p"&gt;]));&lt;/span&gt;

  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="n"&gt;_session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_uri&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="n"&gt;loginUsingMetamask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;connector&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;connected&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;connector&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;createSession&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;onDisplayUri:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="n"&gt;_uri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;launchUrlString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;mode:&lt;/span&gt; &lt;span class="n"&gt;LaunchMode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;externalApplication&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="n"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="n"&gt;_session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&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="n"&gt;Scaffold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;appBar:&lt;/span&gt; &lt;span class="n"&gt;AppBar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nl"&gt;title:&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Login Page'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="nl"&gt;body:&lt;/span&gt; &lt;span class="n"&gt;SingleChildScrollView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nl"&gt;mainAxisAlignment:&lt;/span&gt; &lt;span class="n"&gt;MainAxisAlignment&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;center&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nl"&gt;children:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
              &lt;span class="s"&gt;'assets/images/main_page_image.png'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="nl"&gt;fit:&lt;/span&gt; &lt;span class="n"&gt;BoxFit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fitHeight&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;ElevatedButton&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="nl"&gt;onPressed:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;loginUsingMetamask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Connect with Metamask"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
          &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we run our app 🤞🏾. If everything is done as described, we will be greeted with a familiar Login Page. But when we click on the &lt;code&gt;Connect with Metamask&lt;/code&gt; button, it will redirect to Metamask. Metamask will prompt you to connect your wallet. It will show the URL and icon specified in the &lt;code&gt;clientMeta&lt;/code&gt; field.&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%2Fsdzkbhf6kl62jwgspc63.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%2Fsdzkbhf6kl62jwgspc63.png" alt="Metamask popup" width="407" height="891"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When we click on the blue &lt;code&gt;Connect&lt;/code&gt; button, we will be redirected back to our wallet. Right now we won’t see anything different, but if we check back the logs, you should see flutter printed the account address and the chain id.&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%2Fd7sltsqoivzb0lgwfvr8.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%2Fd7sltsqoivzb0lgwfvr8.png" alt="Showing chainid and account" width="800" height="45"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Congratulations 🥳 🎉!! You have successfully connected with your Metamask wallet and it was that simple.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;There is still one challenge left. Users may not connect with the blockchain your Smart Contracts are deployed to. So before we let users inside our platform, we should check if connected with the correct blockchain. Also, we should update if the user changes the connected network and also the selected account.&lt;/p&gt;

&lt;h3&gt;
  
  
  Subscribing to events
&lt;/h3&gt;

&lt;p&gt;Using our &lt;code&gt;connector&lt;/code&gt; variable we can subscribe to &lt;code&gt;connect&lt;/code&gt;, &lt;code&gt;session_update&lt;/code&gt; and &lt;code&gt;disconnect&lt;/code&gt; event. Paste the following code inside the &lt;code&gt;build&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;connector&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s"&gt;'connect'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;setState&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="n"&gt;_session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_session&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="n"&gt;connector&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s"&gt;'session_update'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="n"&gt;_session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                            &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&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="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;chainId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}));&lt;/span&gt;
    &lt;span class="n"&gt;connector&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s"&gt;'disconnect'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="n"&gt;_session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}));&lt;/span&gt;

    &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we are subscribing to the different events. On a &lt;code&gt;session_update&lt;/code&gt; we update the state of our app using &lt;code&gt;setState&lt;/code&gt; and assign the updated payload inside the &lt;code&gt;_session&lt;/code&gt; variable. We also print the new account address and the chain Id, so that we can check if our code is working properly from the terminal. &lt;/p&gt;

&lt;p&gt;Perform a hot reload of your app and perform the same steps to connect Metamask with your app. Now you can change the network and the connected account from inside Metamask and observe the chain Id and account address change in your terminal/console.&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%2Fcozagymj7ikwxrb2qdck.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%2Fcozagymj7ikwxrb2qdck.png" alt="Updating ChainId and Account" width="800" height="188"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Displaying the data on the screen
&lt;/h3&gt;

&lt;p&gt;We have successfully connected Metamask with our app. Although the tutorial can end right here, I would prefer to display the details on the screen for users to verify and create a better login experience.&lt;/p&gt;

&lt;p&gt;The first thing we want is when the user has connected with Metamask, we want to display the details instead of the button. For this we wrap our &lt;code&gt;ElevatedButton&lt;/code&gt; in a ternary operator as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_session&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;Container&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ElevatedButton&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, if the &lt;code&gt;_session&lt;/code&gt; variable is &lt;code&gt;null&lt;/code&gt;, i.e.  Metamask is not connected, it would render the &lt;code&gt;ElevatedButton&lt;/code&gt; else the &lt;code&gt;Container&lt;/code&gt; will be rendered.&lt;/p&gt;

&lt;p&gt;We start with the following code inside our &lt;code&gt;Container&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;Container&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nl"&gt;padding:&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;EdgeInsets&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fromLTRB&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&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="mi"&gt;20&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="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nl"&gt;crossAxisAlignment:&lt;/span&gt; &lt;span class="n"&gt;CrossAxisAlignment&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nl"&gt;children:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s"&gt;'Account'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;style:&lt;/span&gt; &lt;span class="n"&gt;GoogleFonts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;merriweather&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nl"&gt;fontWeight:&lt;/span&gt; &lt;span class="n"&gt;FontWeight&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;bold&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;fontSize:&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="si"&gt;${_session.accounts[0]}&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;style:&lt;/span&gt; &lt;span class="n"&gt;GoogleFonts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;inconsolata&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;fontSize:&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;We start by adding small padding of &lt;code&gt;20px&lt;/code&gt; from left and right.&lt;/li&gt;
&lt;li&gt;We want our cross-axis alignment to be from the start, so we define &lt;code&gt;crossAxisAlignment&lt;/code&gt; as &lt;code&gt;CrossAxisAlignment.start&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;We want the first widget in our column to be a simple saying &lt;code&gt;Account&lt;/code&gt; and below it shows the account address of the connected Metamask account. We use the &lt;code&gt;Text&lt;/code&gt; widget for displaying the data and use &lt;code&gt;GoogleFonts&lt;/code&gt; for styling. You can import Google fonts by writing&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:google_fonts/google_fonts.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;on top of the file. We use the &lt;code&gt;${}&lt;/code&gt; notation to access the &lt;code&gt;_session&lt;/code&gt; variable inside a pair of single-quote(&lt;code&gt;’’&lt;/code&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The next thing we want to show is the name of the chain users are connected to. We want to display it in the following way:&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%2F21b2iemn4dt68ca0p0ac.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%2F21b2iemn4dt68ca0p0ac.png" alt="Showing Network name" width="622" height="124"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since most of the users may not be familiar with the chain Ids of the different blockchains, it’s better to show them the name of the blockchain, rather than just the chain Id. To do this, we can write a simple function that takes in the &lt;code&gt;chainId&lt;/code&gt; as input and returns the name of the chain. Inside the &lt;code&gt;_LoginPageState&lt;/code&gt; define a function called &lt;code&gt;getNetworkName&lt;/code&gt; as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;getNetworkName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chainId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chainId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Ethereum Mainnet&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Ropsten Testnet&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&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;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Rinkeby Testnet&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Goreli Testnet&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Kovan Testnet&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;137&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Polygon Mainnet&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;80001&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Mumbai Testnet&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Unknown Chain&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The function uses &lt;code&gt;switch-case&lt;/code&gt; statements to return the name of the chain based on &lt;code&gt;chainId&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Inside our &lt;code&gt;Container&lt;/code&gt;, after the two &lt;code&gt;Text&lt;/code&gt; widgets, we add a &lt;code&gt;SizedBox&lt;/code&gt; with &lt;code&gt;height&lt;/code&gt; of 20px to add some gap. Next we define a &lt;code&gt;Row&lt;/code&gt; with two children widgets, the text “Chain” and the name of the chain obtained by calling the &lt;code&gt;getNetworkName&lt;/code&gt; function. We do it like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;Row&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nl"&gt;children:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="s"&gt;'Chain: '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nl"&gt;style:&lt;/span&gt; &lt;span class="n"&gt;GoogleFonts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;merriweather&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nl"&gt;fontWeight:&lt;/span&gt; &lt;span class="n"&gt;FontWeight&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;bold&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;fontSize:&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;getNetworkName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_session&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;chainId&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nl"&gt;style:&lt;/span&gt; &lt;span class="n"&gt;GoogleFonts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;inconsolata&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;fontSize:&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we want to check if the user is connected to the correct network. We check with &lt;code&gt;_session.chainId&lt;/code&gt; matches the chain id of our supported blockchain (in this case 80001 for Mumbai Testnet). If it’s not equal to the required chain id, we create a &lt;code&gt;Row&lt;/code&gt; to display our icon and the helper text, otherwise, we create a &lt;code&gt;Container&lt;/code&gt; that will be used for our &lt;code&gt;SliderButton&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_session&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;chainId&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;80001&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;Row&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;children:&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="n"&gt;Icon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Icons&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;warning&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nl"&gt;color:&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;redAccent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;size:&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Network not supported. Switch to '&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="s"&gt;'Mumbai Testnet'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nl"&gt;style:&lt;/span&gt;
            &lt;span class="n"&gt;TextStyle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;fontWeight:&lt;/span&gt; &lt;span class="n"&gt;FontWeight&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;bold&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Container&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we add out &lt;code&gt;SliderButton&lt;/code&gt;. We import our dependency with the following statement at the start of our file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:slider_button/slider_button.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally inside our &lt;code&gt;Container&lt;/code&gt;, we define our &lt;code&gt;SliderButton&lt;/code&gt; like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;Container&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nl"&gt;alignment:&lt;/span&gt; &lt;span class="n"&gt;Alignment&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;center&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;SliderButton&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nl"&gt;action:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// TODO: Navigate to main page&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="nl"&gt;label:&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Slide to login'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nl"&gt;icon:&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Icon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Icons&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;check&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;For now, the &lt;code&gt;SliderButton&lt;/code&gt; doesn’t do anything, but in further tutorials, it will navigate us to the main page of our application.&lt;/p&gt;

&lt;p&gt;Now your app is fully ready to be run. If everything was done as described in this tutorial, your app should be now ready. You should be able to Login In to your app using Metamask. Although the app doesn’t login into any page, still you can connect with Metamask using your mobile app. &lt;strong&gt;&lt;em&gt;How awesome is that ?!!&lt;/em&gt;&lt;/strong&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Wow!! That was a log tutorial. In this tutorial, we covered how to build a very basic flutter app from scratch. We learned how to interact with Metamask from our app. We explored two important dependencies, &lt;code&gt;walletconnect_dart&lt;/code&gt; and &lt;code&gt;url_launcher&lt;/code&gt;, and learned how they work and how they can be used to connect an app with a wallet like Metmask. We also learned how to update our app when the user updates the Metamask session. And finally, I hope we all had a great time learning something new and interesting.&lt;/p&gt;

&lt;p&gt;The code for this project is uploaded to Github &lt;a href="https://github.com/BhaskarDutta2209/FlutterAppWithMetamask" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I plan to extend this application into an app that does more cool things and dive deeper into the world of Defi, Blockchain, and beyond. If you liked this tutorial, don’t forget to show your love and share it on your socials or help me improve by posting your feedback in the Discussion. If you want to connect with me or recommend any topic, you can find me on &lt;a href="https://www.linkedin.com/in/itsbhaskardutta/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;, &lt;a href="https://twitter.com/Bhaskar2209" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;, or through my mail.&lt;/p&gt;

&lt;p&gt;We will meet again with another new tutorial or blog, till then stay safe, spend time with your family and &lt;strong&gt;&lt;em&gt;KEEP BUIDLING!&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>metamask</category>
      <category>flutter</category>
      <category>blockchain</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
