Web3 backend and smart contract development for Python developers Musical NFTs part 13: Connecting MetaMask
Published: 2023-10-29 22:20:28

In this part we will add ability for crypto users to connect his/her MetaMask and to purches new NFT with our MockUSDC tokens. But before that let's clean a bit our `home.html` because it started to look a bit messy. What we can do is to create two new templates for crypto buyers and credit card buyer and to loaded them into `home.html` when we check user payment method status. For this to happen we just need to repackage our `home.html` and to move code related to crypto buyer to newly created `templates/cypto_user.html` and then all HTML code related to credit card buyer to `templates/credit_card_buyer.html`. Then in second step we will use Django tag `include` to include this two newly created HTML files into our `home.html`. With this we will clean up cluttery and make our main `home.html` template a bit more readable. 

Create `cypto_user.html` and `credit_card_user.html` files inside root `templates` folder. 

`cypto_user.html`

    

```
<table class="table  table-hover">
    <thead class="table-dark">
      <tr>
        <th scope="col">Name</th>
        <th scope="col">Email</th>
        <th scope="col">Total no. NFTs</th>
        <th scope="col">Means of payment</th>
        <th scope="col">Buy NFT</th>
      </tr>
    </thead>
    <tbody>
      <tr>
          <td> {{ customer.first_name }} {{ customer.last_name }} </td>
          <td> {{ customer.email }} </td>
          <td> {{ customer.total_no_of_nfts }} </td>
          <td>
            <form action="" method="post">
            {%csrf_token%}
            {{orderForm.as_p}}
            <input type="submit" value="Save" class="btn btn-secondary">
        </form>
          </td>       
          <td>
            <form action="" method="post">
            {%csrf_token%}
            {{form.as_p}}
            <input type="submit" value="Save" class="btn btn-secondary">
            </form>
          </td>             
          
        </tr>
      </tbody>
    </table>      
    {% for card in metadata%}
    {% if forloop.counter0|divisibleby:3 %} <div class="row">{%  endif %}
      <div class="card m-5 p-2" style="width: 18rem;">
        {% load static %}
        <img src="{% static 'nft/'%}{{card.cover_file_name}}"  class="card-img-top" alt="..." width="50" height="200"/>
        <div class="card-body">
          <h5 class="card-title">{{card.name}}</h5>
          <br>
          <p class="card-text">{{card.description}}</p>
        </div>
      </div>
    {%  if forloop.counter|divisibleby:3 or forloop.last %}</div> {%  endif %}
    <br>
    {% endfor %}
```




And then in `credit_card_user.html`

    
    

```
<table class="table  table-hover">
    <thead class="table-dark">
      <tr>
        <th scope="col">Name</th>
        <th scope="col">Email</th>
        <th scope="col">Total no. NFTs</th>
        <th scope="col">Means of payment</th>
      </tr>
    </thead>
    <tbody>
      <tr>
          <td> {{ customer.first_name }} {{ customer.last_name }} </td>
          <td> {{ customer.email }} </td>
          <td> {{ customer.total_no_of_nfts }} </td>
          <td><form action="" method="post">
            {%csrf_token%}
            {{orderForm.as_p}}
            <input type="submit" value="Save" class="btn btn-secondary">
        </form>
          </td>         
        </tr>
      </tbody>
    </table>        
    {% for card in metadata%}
    {% if forloop.counter0|divisibleby:3 %} <div class="row">{%  endif %}
      <div class="card m-5 p-2" style="width: 18rem;">
        {% load static %}
        <img src="{% static 'nft/'%}{{card.cover_file_name}}"  class="card-img-top" alt="..." width="50" height="200"/>
        <div class="card-body">
          <h5 class="card-title">{{card.name}}</h5>
          <br>
          <p class="card-text">{{card.description}}</p>
        </div>
      </div>
    {%  if forloop.counter|divisibleby:3 or forloop.last %}</div> {%  endif %}
    <br>
    {% endfor %}
    <p> credit card </p>

```

Now what we need to do is to include back into our `home.html` this two new files via Django template language tag `include`. Syntax should go something like this 
`{% include "crypto_user.html" %}` 


And now our `home.html` should look a bit shorter and cleaner

    

```
{% extends "base.html" %}
    {% block content%}

    {% if user.is_authenticated %}
        {% if customer.type == "CRYPTO"%}
        {% include "crypto_user.html" %}    
        
        {% else %}
        {% include "credit_card_user.html" %}    
        
        {% endif %}
        {% else %}
        <div class="col-md-6 offset-md-3"> 
        <h1> Login </h1>
        <br/>
        <form method="POST" action="{% url 'home' %}"> 
            {% csrf_token %}        
                <div class="mb-3">
                <input type="text" class="form-control" aria-describedby="emailHelp" placeholder="Username" name="username" required>
                </div>
                <div class="mb-3">
                <input type="password" class="form-control" placeholder="Password" name="password" required>
                </div>
                <button type="submit" class="btn btn-secondary">Login</button>
            </form> 
        </div>
    {% endif %}
    {% endblock content%}
```


Now all things should work exactly the same only thing is that we have more readeble main html document. 

Let's move to web3 part. For now our aim is to integrate MetaMask (you can easlly experiment with WalletConnect if you want alternative version of this code). This will allow crypto user to purches new NFT by using MetaMask. For this to happen we will need to use some JavaScript (in next iteration of this app, when we start to use React for our frontend we will integrate WalletConnect instead of MetaMask).  

Ones crypto user login into his profile he will see two new buttons: connect and buy NFT. He first need to press connect and MetaMask will pop-up asking him to provide his credentials. Ones he finish login into MetaMask he will be able to use buy NFT button and to pass number of NFTs he would like to buy. 

Step 1: In your static folder create new `connect_wallet.js` file. And inside that file pass following code (Please check if static parameters are set correctly inside your `settings.py` It should look something like this =>


  

```
  STATIC_URL = "/static/"
    STATICFILES_DIRS = (
        os.path.join(BASE_DIR, 'static'),
    )
    STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
```


JavaScript file need to handle connection to MetaMask as well as to update list items to `connected` or `connect to metamask` status how they change. For this achive we will need few more functions. 

   

```
 //function used to connect to MetaMask wallet
    connect = async () => {
        const address = await ethereum
        .request({
            method: 'eth_requestAccounts',
            params: [],
        })
        .then((res) => console.log('request accounts', res))
        .catch((e) => console.log('request accounts ERR', e));
        document_test = document.getElementById("connect");
        document_test.innerHTML = "Connected"  
    }   

    // Simple function used to manipulate HTML elements according to connected or user disconnencted status
    checkMetaMaskState = async () => {
        const account = await window.ethereum.request({method: 'eth_accounts'})
        const liElement = document.createElement("li");
        liElement.setAttribute("class", "nav-item")
        const aElement = document.createElement("a");
        aElement.setAttribute("class", "nav-link p-3")
        if (typeof account[0] == "undefined") {
            aElement.setAttribute("href", "javascript:connect()")
            aElement.setAttribute("id", "link")
            liElement.setAttribute("id", "connect")
            liElement.innerHTML = "Connect to MetaMask"
            aElement.appendChild(liElement);
        document.getElementById("logout").appendChild(aElement);
    } else if (account[0].includes("0x")) {
        aElement.setAttribute("id", "link")
        liElement.setAttribute("id", "connect")
        liElement.innerHTML = "Connected"
        aElement.appendChild(liElement);
        document.getElementById("logout").appendChild(aElement);
    } else {
        console.log("There is some problem with MetaMask")        
    }
    }

    // Detect change in connect or dissconcet wallet status and updated front-end accordingly
    window.ethereum.on('accountsChanged', async () => {
    let ilElement = document.getElementById("connect")
    const account = await window.ethereum.request({method: 'eth_accounts'})
    if (typeof account[0] == "undefined") {
        ilElement.innerHTML = "Connect to MetaMask"
    } else if (account[0].includes("0x")) {
        ilElement.innerHTML = "Connected"
    }
    });
```


Then we need to add `onload` in body element of our `base.html`. And then to give `checkMetaMaskState` JS funciton as value. This function is used to generate new HTML document according to MetaMask connect/disconnect status.   

Now `base.html` should look something like this (bascially the same as beafore just with `<body onload="checkMetaMaskState()">` added)


    

```
{% load static %}
    <!doctype html>
    <html lang="en">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Muscial NFT</title>
        <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
        <script type="text/javascript" src="{% static 'connect_wallet.js' %}"></script>
        
    </head>
    <body onload="checkMetaMaskState()">
        {% include "navbar.html"%}
        <div class="container ">       
            <br/>
            <br/>
            {% if messages %}
            {% for message in messages%}
            <div class="alert alert-warning alert-dismissible fade show" role="alert">
            {{ message }}
            <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
            </div>
            
            {% endfor%}
            {% endif %}
            
            {% block content %}
            {% endblock content %}
        </div>
        <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL" crossorigin="anonymous"></script>
    </body>
    </html>

```

Then in second step we will erase one list item element from our `navbar.html` template (this place will be populated directly from javascript level according to MetaMask wallet status).  

    

```
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
      <div class="container-fluid">
        <a class="navbar-brand" href="{% url 'home' %}">Musical NFT </a>
        <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
          <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbarSupportedContent">
          <ul class="navbar-nav me-auto mb-2 mb-lg-0" id="logout">
            {% if user.is_authenticated%}
              {% if customer.type == "CRYPTO"%}
              {% load static %}
              <script type="text/javascript" src="{% static 'connect_wallet.js' %}"></script>
                <li class="nav-item"  >
                  <a class="nav-link p-3" href="{% url 'logout'%}"  >Logout</a>
                </li>
                {% else %}
                <li class="nav-item">
                  <a class="nav-link" href="{% url 'logout'%}">Logout</a>
                </li>

                {% endif %}
                
          {% else %}
          <li class="nav-item">
            <a class="nav-link" href="{% url 'register'%}">Register</a>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="{% url 'home'%}">Login</a>
          </li>
          {% endif%}
              </ul>
            </li>
          </ul>
        </div>
      </div>
    </nav>
```

If everything went well ones you login Denis user into his account you should be able to see something like this. 



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/es0sgicjov58y57094be.png)


Code can be found in this github [repo](https://github.com/ilijapet/musical_nft_thumbnails)