Web-based NFT Wallet using Zilliqa Js API and ZilPay | Part-3

Vikram
Builders of Zilliqa
8 min readAug 25, 2021

In part one of the series, we deployed our NFT contract called StarNFTz, got ourselves familiar with tools like Savant IDE and ViewBlock explorer. In the second part, we explored the Zilliqa Js library provided by ZilPay wallet and tried some really cool code to interact with wallet, blockchain, and contracts.

In this 3rd part, we will be building the a NFT gallery for which you all have been waiting for so long 😁. So let’s start with part-3 of our series 🙌🏻

Part 3— Build an NFT Gallery

Before starting, let’s go through some requirements that we may need in this part of the series.

System Requirement and Setup

For this part, we will mostly be using a code editor, a browser, and a ZilPay wallet. Feel free to use any editor and browser of your choice. I will be using the sublime text editor, chrome browser with the ZilPay wallet extension.

I will be dividing this part into the following two sections:

  • Designing the gallery UI: In this section, we will design a simple gallery UI with some plain HTML and CSS code. We will also, design a card to represent our NFT.
  • Javascript code for gallery: In this section, we will write some Js code to fetch our NFTs from blockchain and dynamically load them into our gallery.

The reason we are just focused on the gallery UI and not the entire wallet UI is to keep it as simple as possible, focusing more on understanding how things work and not making it more complex at this point in time. So let’s start with the first section of this part.

3.1 Designing the gallery interface.

In this section, we will be designing a gallery UI. To start with, make a new project folder and create an index.html file inside it. Type the following code in this index.html file and save it.

<!DOCTYPE html>
<html>
<head>
<title>StarNFTz</title>
<style type="text/css">
body {
background: linear-gradient(-45deg, #ee7752, #e73c7e, #23a6d5, #23d5ab);
background-size: 400% 400%;
}
#gallery-container {
width: 60%;
border-width: 1px;
border-style: solid;
border-color: wheat;
display: flex;
justify-content: center;
flex-flow: wrap;
}
</style>
</head>
<body>
<center>
<div class="gallery-container">
Gallery Here
</div>
</center>
</body>
</html>

This code does nothing much, it just defines a div tag with a id called gallery-container and some CSS defined for it in the style tag. Now load the page in your web browser and it should show something like following:

Index.html with an Empty Gallery

Now, let’s design our NFT card UI inside gallery-container. We will create one card and then replicate it multiple times. In the final code, this will be handled dynamically by Javascript codes. Type the following code in the gallery-container div to add HTML for our NFT cards.

<div class="nft-card">
<div class="nft-card-id HVCenter">NFT ID</div>
<div class="nft-card-img-holder HVCenter"><img src="https://raw.githubusercontent.com/NakamotoVikram/Web-Based-NFT-App-On-Zilliqa/master/StarPictures/P13R.png"></div>
<div class="nft-card-owner HVCenter">Owner 0x</div>
</div>

The code is pretty simple; it defines a div tag with three sub-divs each to represent NFT id, NFT image, and NFT owner. Now, put the following CSS code in the style tag which defines styling for our NFT card.

.nft-card {
width: 200px;
height: 260px;
margin: 8px;
padding: 1px;
border: solid 1px black;
background-color: gold;
}
.nft-card-id {
height: 10%;
}

.nft-card-owner {
height: 10%;
overflow-x: scroll;
}

.nft-card-img-holder {
height: 80%;
}

.nft-card img {
width: 100%;
}

.HVCenter {
display: flex;
justify-content: center;
align-items: center;
}

Save this code and load the page in your browser. It should now show one NFT card displayed in the gallery. Now replicate the nft-card div multiple times the gallery and you can see something like following 😃

Gallery with lots of sample NFT cards

Congratulations Zilliqan! We had finally made our gallery UI 😅, doesn't that look amazing!

That was it for this section. In the coming sections of this part we will see a lot more interesting things but before moving on to it, let's see an ad-hoc section on how to set up a local server for testing.

Setting Up A Local Server

In the previous section, we build our UI and tested it just by loading it in the browser from the file system. Also, in the previous part, we tested a few Zilliqa JS codes using the dev console on a webpage loaded from some server on the internet.

Now, we need a mechanism where we need to make Zilliqa Js work on our app page for which we need to load our page from some Internet or local HTTP server. To do so, we will be using a local HTTP server using Python as it is easy to use and readily available in many systems. You can surely explore other mechanisms as well, but what we need is a simple HTTP server to serve our app.

To steps to start an HTTP server using Python are as follows:

1. Open the terminal or any equivalent tools on your system.2. Goto the directory where your app/index.html is stored using the cd or equivalent command.3. Now to start a server type the following command depending on the version of python you have:-  For python3:
> python3 -m http.server
For older python version:
> python -m SimpleHTTPServer <Port>
4. The above cmd will print some port number which we can now use to access our app directory using the url http://localhost:<portNo> in your browser. By default it loads index.html.

I run my local server using python3 and the result is as follows:

Running a Python Serve

3.2 Javascript code for our gallery

So far we have our gallery UI ready and we know how to run and test our app from a local server, now let’s get back to our gallery and add some Javascript code to it.

Let’s create a Javascript file called script.js in the same project folder as we created index.html and link it using a script tag in our index file.

We will start by defining a few global variables and some functions in our script.js file that we will be needing to build our gallery. Let’s start by defining the following three global variables:

var ContractAddress = "0x031f45f25df417a3d145dbc5d01e20153ac505ef";
var ContractObject;
var ContractState;

Here ContractAddress is the variable that stores our contract address. For now, we had hard-coded it to our StarNFTz contract. Similarly, ContractObject and ContractState will store our contract and its state respectively.

Now let’s define three functions called checkWallet connectWallet and loadContract as follows:

function checkWallet(){
if(window.zilPay){
return true;
}else{
return false;
}
}
async function connectWallet(){
return (await window.zilPay.wallet.connect());
}
function loadContract(contractAddr){
try{
return window.zilPay.contracts.at(contractAddr);
}catch(err){
console.log(err.message);
return false;
}
}

Most of this code is self-explanatory and is no different than the code we saw in the previous part of this series. Now let's define one more function called onloadInits() in our script file that we will execute as soon as our app is loaded.

async function onloadInit(){
check1 = checkWallet();
check2 = await connectWallet();
if(check1 && check2){
ContractObject = loadContract(ContractAddress);
if(ContractObject){
ContractObject.getState().then(function(stateData){
ContractState = stateData;
//alert("Contract State Loaded Successfully!")
loadGallery();
});

}
}
}

This function makes use of all the functions we defined above to make all the required checks and establish a connection if not. Then, it loads the contract state from the blockchain and stores it into a global ContractState variable as highlighted above.

In order to make it call after the app is loaded, we need to add a onload attribute to our <body> tag as shown below:

<body onload="onloadInit()">

If you have noticed, we have called a loadGallery() function in onLoadInit() function that will be responsible for building our gallery. So let's go ahead and add the following code for loadGallery() function in our script.js file

function loadGallery(flag){
var gallery = document.querySelector("#gallery-container");
gallery.innerHTML = "Loading Gallery....";
tokenOwners = ContractState.token_owners;
tokenUris = ContractState.token_uris;
galleryCode = "";for(i in tokenOwners){
galleryCode += `
<div id="nft-
${i}" class="nft-card">
<div class="nft-card-id HVCenter">NFT ID:
${i}</div>
<div class="nft-card-img-holder HVCenter">
<img src="
${tokenUris[i]}"></div>
<div class="nft-card-owner">Owner:&nbsp;
${tokenOwners[i]}</div>
</div>
`
;
}
gallery.innerHTML = galleryCode;
}

Here loadGallery() function does two important things, one manipulates DOM i.e the HTML page, and two loops through the token list called token_owners and keeps on adding NFT card to the gallery. You can read more about DOM here.

token_owners has a token id to owner address mapping and token_uris has a token id to token image location mapping. We can link both these mapping using their common key `token id` to build our NFT card. The for-loop in the code loops through the token owners for each token id i and keep on appending the new card to a variable called galleryCode

If you have noticed, the HTML for NFT cards is the same as what we defined earlier with a little information added to it dynamically using the ${<variable-name>} syntax. Also, we have given a id to each NFT card as nft-<token_id> which we may use in the latter part of the series.

That was it, now our gallery is ready to be tested. Head over to your browser, load your app and it should give you something like this 🤩

NFT gallery with StarNFTz Contract Loaded from Testnet

So far, I had only 5 NFTs minted hence its shown me 5 NFTs in my gallery. By the time you see it, there may be more if I mint some news ones in the latter part of the series.

Now, try this out again with one of your NFT contracts on testnet or with this 0xb4d83becb950c096b001a3d1c7abb10f571ae75f DragonZil contract address on the mainnet by changing the ContractAddress variable. Our gallery code is very general and should work with any contract until and unless the NFT is an image type and have state variables token_owner and token_uris.

I got the following result when I switched my wallet to the main network and changed the ContractAddress to the DragonZil address. It loads all hundreds of DragonZil NFTs in our gallery 😁 Isn’t that cool, surely it is! and you all should also try it out once, it's really fun 😅.

Gallery with DragonZil Contract Loaded from Mainnet

After looking at this, now you might have got an idea that our app is not just limited to StarNFTz but can be a more general NFT wallet. That's right and it is what we are targeting to build in the coming part of the series.

Zilliqans, that was it for Part3 of this series, hope you all liked it and had fun building the NFT gallery 😁. In the next part, we will try to transform our NFT gallery into a full-fledged general NFT wallet where we can transfer, mint, and load new NFTs. Till then, stay tuned and stay safe 😃

If you have any feedback, suggestions, or inputs feel free to write me on Twitter @NakamotoVikram

--

--