# How to Build an NFT Viewer dApp using Ankr.js to fetch NFTs owned by the Wallet Address

### What Are We Building

In this tutorial, we will be building an NFT viewer using Ankr.js, React, TypeScript, Next.js, Vercel, and TailwindCSS. The React web app will provide a user interface that displays a grid view of all the NFTs held by any given wallet address input. NFT data fetched using Ankr.js.

![nft gallery final.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1664605317606/JPrSuYO6k.png align="left")

[Ankr.js](https://github.com/ankr-network/ankr.js) is a JavaScript library that lets us interact with [Ankr's Advanced API's](https://www.ankr.com/advanced-api/) to fetch data from the eight supported EVM-compatible blockchains:

*  Ethereum
*  Fantom
*  Binance
*  Polygon
*  Syscoin
*  Arbitrum
*  Avalanche
*  Optimism

and more EVM and non-EVM chains coming soon.

_____________________

**By the end of this tutorial, you will be able to:
**
- Install, set up, and initialize the Ankr.js library. 
- Create a new Next.js project and learn how to use the Ankr.js library to interact with Ankr's Advanced APIs for data retrieval.
- Fetch and store NFT data retrieved for a wallet address into a state variable and display the results to the user interface. 
_____________________

[![D_D Newsletter CTA](https://sitemedia.ams3.digitaloceanspaces.com/blog_banner_v1_d1653cce08.png)](https://devdao.to/blog-newsletter-1)

## The Functionalities

1. Users will be able to input a wallet address into the "Wallet address" field. 
2. The app will interact with the provider API endpoints and fetch the NFT data using Ankr.js.
3. The app returns a gallery grid view of all the NFTs held by the wallet address to the user interface. 
___________________________
## The Tech Stack

- CSS Framework: [Tailwind](https://tailwindcss.com/)
- RPC Provider: [Ankr Protocol](https://www.ankr.com/)
- JavaScript Libraries: [Ankr.js](https://www.npmjs.com/package/@ankr.com/ankr.js), [React](https://reactjs.org/tutorial/tutorial.html)
- Frontend/Framework: [TypeScript](https://www.typescriptlang.org/), [Next.js](https://nextjs.org/)

____________________

## Getting Started

#### The Prerequisites:

- Have [Git](https://git-scm.com/downloads), [Yarn](https://yarnpkg.com/), [TailwindCSS](https://tailwindcss.com/docs/guides/nextjs), and [Node.js](https://nodejs.org/en/download/) installed on your machine.
- Basic understanding of [JavaScript](https://www.codecademy.com/learn/introduction-to-javascript), [React](https://reactjs.org/tutorial/tutorial.html), and [TailwindCSS](https://tailwindcss.com/).
______________

## Step 1: Create Next.js Project

Open up a terminal on your machine and navigate to the preferred directory location where you want to store your Next.js project and run the following command:

```zsh
yarn create next-app --ts ankrjs-tutorial
```

This command creates a new Next.js starter project called `ankrjs-tutorial`. Now, let's navigate into the `ankrjs-tutorial` project directory and launch the local development server by running the following command:

```zsh
cd ankrjs-tutorial && yarn dev
```

The above command changes your active directory to `ankrjs-tutorial` and sets up your local development environment. Copy and paste `http://localhost:3000` into your web browser to launch the Next.js starter project. Here's what your web browser should look like: 

![next.js.jpg](https://cdn.hashnode.com/res/hashnode/image/upload/v1664587692802/MRPL04cpG.jpg align="left")

The app currently only contains the starter code provided by Next.js and we will be updating it throughout this tutorial to customize the frontend UI of our NFT wallet gallery web app. 

Now let's install `tailwindcss` and its peer dependencies via npm by running the following command in your terminal:

```zsh
npm install -D tailwindcss postcss autoprefixer
```

Run the `init` command to generate both `tailwind.config.js` and `postcss.config.js` files:

```zsh
npx tailwindcss init -p
```

Add the paths to all of your template files in your `tailwind.config.js` file by updating the code with the below:

File `./tailwind.config.js`

```javascript
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    "./pages/**/*.{js,ts,jsx,tsx}",
    "./components/**/*.{js,ts,jsx,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}
```

Now add the `@tailwind` directives for each of Tailwind's layers to your `globals.css` file. The top of your `global.css` file should look like this:

File: `./styles/globals.css`

```css
@tailwind base;
@tailwind components;
@tailwind utilities;

...
```

______________


## Step 2: Install & Set Up Ankr.js

For our NFT viewer to be able to communicate with the different blockchain providers and download the data from, we'll need to install and set up Ankr.js. This JavaScript library allows us to fetch data using Ankr's Advanced APIs including NFT metadata, account balance, token holders, transactions, and more from the supported EVM-compatible blockchains. The primary datapoint we will be retrieving for this tutorial will be the list of NFTs owned by any given wallet address input.

In the project root directory `ankrjs-tutorial`, run the following command in your terminal to install the `ankr.js` library:

```zsh
yarn add @ankr.com/ankr.js
```

In the same directory, create a new file named `utils.ts` by running the following command in your terminal:

```zsh
touch utils.ts
```

Now let's initialize the Ankr.js library by adding the following code in the new `utils.ts` file we created in the previous step:

File: `./utils.ts`

```typescript
import AnkrscanProvider from '@ankr.com/ankr.js';

const provider = new AnkrscanProvider(' ');
```

The `provider` instance is our interface to Ankr's Advanced APIs whenever we need to fetch data or interact with them. 

______________


## Step 3: NFT Retrieval Function

In this section, we'll create the `getNfts` function that accepts the wallet address as the user input and returns the collection of NFTs owned by the input address. Ankr.js library provides us with the `getNFTsByOwner` method that we will implement and utilize inside of our `getNfts` function.

The NFT viewer app will accept input for Ethereum, Polygon, and Binance wallet addresses. Update the `utils.ts` file with these function and method implementations code provided below.

The updated `utils.ts` file should look something like this:

File: `./utils.ts`

```typescript
import AnkrscanProvider from '@ankr.com/ankr.js';

const provider = new AnkrscanProvider(' ');

export const getNfts = async (address: string) => {
  const { assets } = await provider.getNFTsByOwner({
    walletAddress: address,
    blockchain: ['eth', 'polygon', 'bsc'],
  });
  return {
    nfts: assets,
  };
};
```

Now, let's test it out by calling the function and logging the output onto our browser's console. We will use the `useEffect` [_Hook_](https://reactjs.org/docs/hooks-intro.html) which tells React that our component needs to do something after it renders. 

Update the code inside the `index.tsx` file with the following lines of code: 

File: `./pages/index.tsx`

``` typescript
import type { NextPage } from 'next';
import { useEffect } from 'react';
import { getNfts } from '../utils';

const Home: NextPage = () => {
  useEffect(() => {
    (async () => {
      const { nfts } = await getNfts(
        '0xe4bBCbFf51e61D0D95FcC5016609aC8354B177C4'
      );
      console.log({ nfts });
    })();
  }, []);

  return (
    <div className='p-10 flex flex-col items-center'>
      <h1 className='text-3xl tracking-tight font-extrabold text-gray-900 sm:text-4xl md:text-6xl mb-4"'>
          NFT Viewer
       </h1>
    </div>
  );
};

export default Home;
```

In this case, the `useEffect` _Hook_ retrieves the list of NFTs owned by the wallet address. Then the collection of NFTs owned by the the address are stored in the `nfts` array and logged to the browser's console.

Your browser's console log should look similar to this:

![screenshot console log nft list.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1664589723801/hir8uJCLn.png align="left")
______________

## Step 4: Create Wallet Address Input

In this step, we're going to add an input element to the user interface that allow users to input any wallet address and pass it to the `getNfts` function. 

We will use the `useState` [_Hook_](https://reactjs.org/docs/hooks-state.html) to keep track of the wallet address in a state variable named `walletAddress`, hook it up to the input element in the user interface and pass it to the `getNfts` function.

Your updated `index.tsx` file should have the following lines of code and look something like this:

File: `./pages/index.tsx`

```
/* eslint-disable @next/next/no-img-element */
import type { NextPage } from 'next';
import { useEffect, useState } from 'react';
import { useNfts } from '../hooks';
import { getNfts } from '../utils';

const Home: NextPage = () => {
  const [walletAddress, setWalletAddress] = useState(
    '0xe4bBCbFf51e61D0D95FcC5016609aC8354B177C4'
  );

  useEffect(() => {
    (async () => {
      const { nfts } = await getNfts(walletAddress);
      console.log({ nfts });
    })();
  }, [walletAddress]);

  return (
    <div className='p-10 flex flex-col items-center'>
      <h1 className='text-3xl tracking-tight font-extrabold text-gray-900 sm:text-4xl md:text-6xl mb-4"'>
            NFT Viewer
       </h1>

      <div className='flex-left flex-col mt-4'>
        <label className='text-zinc-700 text-2xl font-extrabold' htmlFor='wallet-address'>
         &nbsp; Wallet address: &nbsp;
        </label>
        <input
          id='wallet-address'
          type='text'
          value={walletAddress}
          onChange={(e) => setWalletAddress(e.target.value)}
          className='rounded p-3 w-[425px] border'
          placeholder='Enter a wallet address here to view NFTs'
        />
      </div>
    </div>
  );
};

export default Home;
```

A different list of `nfts` are logged out into the browser console anytime the wallet address changes in the input now. Finally, we are able to fetch the list of NFTs held by any given input address. 

The console log should look something like this: 

![walletaddress input.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1664591735928/aL0y3rtdO.png align="left")
______________

## Step 5: Display NFT Gallery

We're almost done with our NFT viewer. In this step, we will store the list of NFTs we fetched into a state variable named `nfts`, log it to the console, then loop through the `nfts` array, and return a gallery grid view to the user interface. 

The most updated `index.tsx` file should look something like this:

File: `./pages/index.tsx`

```typescript
/* eslint-disable @next/next/no-img-element */
import type { NextPage } from 'next';
import { useEffect, useState } from 'react';
import { useNfts } from '../hooks';
import { getNfts } from '../utils';

const Home: NextPage = () => {
  const [walletAddress, setWalletAddress] = useState(
    '0xe4bBCbFf51e61D0D95FcC5016609aC8354B177C4'
  );
  
  const { nfts, loading, error } = useNfts(walletAddress);

  useEffect(() => {
    (async () => {
      const { nfts } = await getNfts(walletAddress);
      console.log({ nfts });
    })();
  }, [walletAddress]);

  return (
    <div className='p-10 flex flex-col items-center'>
      ...
      <div className='grid grid-cols-4 mt-8 gap-4'>
        {nfts.map((nft) => {
          return (
            <div
              key={`${nft.contractAddress}/${nft.tokenId}`}
              className='flex flex-col rounded border p-4'
            >
              <img
                className='w-[200px] h-[200px] rounded shadow'
                src={nft.imageUrl}
                alt={nft.name}
              />
              <span className='font-bold mt-8'>{nft.name}</span>
              <span>{nft.collectionName}</span>
            </div>
          );
        })}

        {error && (
          <div className='flex flex-col items-center mt-8'>
            <p className='text-red-700'>
              Error: {JSON.stringify(error, null, 2)}
            </p>
          </div>
        )}
      </div>

      <footer className='flex flex-col gap-2 mt-16 items-center'>
        <Link href='https://github.com/theekrystallee/ankrjs-tutorial'>
          <a className='text-zinc-700 underline'>Source code</a>
        </Link>
      </footer>
    </div>
  );
};

export default Home;
```
______________

## Step 6: Deploy NFT Viewer

Now let's deploy our Next.js app with Vercel by following the steps below:

1. Go to [Vercel](https://vercel.com/dashboard) and sign in with your GitHub account.
2. Click the `New Project` button and select your project repo.
3. Select the Framework as `Next.js`.
4. Click `Deploy` and now your [NFT viewer](https://ankrjs-tutorial.vercel.app/) is live!

Congrats on successfully completing this tutorial! You should now see a gallery grid view of all the NFTs owned by the input wallet address returned to the user interface. 

![nft gallery final.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1664605317606/JPrSuYO6k.png align="left")

______________

[![D_D Newsletter CTA](https://sitemedia.ams3.digitaloceanspaces.com/blog_banner_v1_d1653cce08.png)](https://devdao.to/blog-newsletter-1)


### Additional Resources

%[https://github.com/theekrystallee/ankrjs-tutorial]

%[https://www.ankr.com/docs/advanced-api/javascript-sdk/]

%[https://blog.developerdao.com/build-a-full-stack-nft-allowlist-dapp]

_________________
## Where to Find Me

Feel free to reach out to me with any questions on Twitter [@theekrystallee](https://twitter.com/theekrystallee) or show me what you learned on TikTok [@theekrystallee](https://www.tiktok.com/@theekrystallee).

Happy building 🧱
