# Build NFT Gated Dapp

In this sample project tutorial, we will learn about Utility NFTs and how we can use an NFT as an access token to a web portal.

By the end of this tutorial, you will be able to build your very own NFT gated dapp similar to&#x20;

[Shyft's Landing pass project.](https://nft-as-access-token.vercel.app/)

<figure><img src="https://2394289113-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F4XnSsBH76iytbI7NwX5o%2Fuploads%2FaWXgYxstMstENdGPBrIu%2FScreenshot%20(547).png?alt=media&#x26;token=f8ddd23b-cac1-4c1e-a4eb-4a8964c98d39" alt=""><figcaption></figcaption></figure>

### What are Utility NFTs?

Utility NFTs, or NFTs with utility are special kind of NFTs which have use cases that go beyond just being one-of-a-kind NFTs. They are NFTs that give their owners special privileges, access rights, or prizes that they would not otherwise have.

Utility NFTs may be useful in various scenarios. One such scenario may be, if we have a private party, and 200 people are to be invited, we can printout and issue 200 invitation passes. Each pass will be non-fungible. However, every individual pass grants the same privilege, in this instance that is admission to the private party. The party organizer could provide 200 utility NFTs instead of 200 printed invitations. The NFTs will be distinct, non-fungible, and will function exactly like the printed invitation, i.e. they will grant admission to the private party.

Even though discovering real-world use cases for NFTs is at a very early stage, the cryptographically distinct tokens have the potential to be more than just JPEGs stored on a specific blockchain. Utility NFTs, or NFTs with real-world applications, may potentially be the catalyst for the transition of NFTs from just an investment fad to a brand new mode of interaction, play, and work. In the following sample project tutorial, we will see how we can use an NFT as an access token. We will check if one particular NFT is in your wallet or not (using [SHYFT APIs](https://https/shyft.to/)), and accordingly, we will grant you access to a portal.

Read SHYFT Documentation [here](https://docs.shyft.to/).

### Pre-requisites for the project

To get started, we will need a few things.

#### Authentication: Get your Shyft API key

`x-api-key` is an authentication parameter, which gives you access to SHYFT APIs. You can get your own API Key from the [SHYFT website](https://shyft.to/get-api-key). Just signup with your email id [here](https://shyft.to/get-api-key) and you can get it for free.

#### Phantom Wallet

We will need the Phantom wallet browser extension, you can download it from the link below.

* [Chrome/Brave](https://chrome.google.com/webstore/detail/phantom/bfnaelmomeimhlpmgjnjophhpkkoljpa).
* [Firefox](https://addons.mozilla.org/en-US/firefox/addon/phantom-app/).

Once done, set up your Phantom wallet account. On-screen tips are available, which will guide you through setting up and getting started. You can also find a detailed guide related to this [here](https://news.coincu.com/2433-the-easiest-guide-to-using-phantom-wallet-on-solana/).

We will use [React](https://reactjs.org/) to develop this project but you can choose any language of your choice. As we are using react we will need Node.js installed on our computer. You can download node.js from [here](https://nodejs.org/en/download/).

### Let's start building

In this sample project, we will design a web portal and grant users access to that particular web portal based on one particular type of NFT in their wallet. We will first use [SHYFT's](https://https/shyft.to/) `read_all` API to access a list of all NFTs in the user's wallet and check for an NFT with a specified update authority, or any specific attribute. If found, we will navigate the user to a new web portal.

If we cannot find the specified NFT, we can provide the user an option to mint a new NFT using SHYFT APIs.

**Create React App**

To create a new react app, navigate to the directory in which you want to create a react app and open the terminal in that particular directory. Then use the following command to create a new react application.

```bash
npx create-react-app access-app
```

This will create a new react application and we will be all set to start creating our new react application.

**Code Editor**

We have used [`VScode`](https://code.visualstudio.com/) as our code editor for this project but you can use any editor of your choice such as Sublime text, Notepad++, Atom, or any editor of your choice. Once decided, let's open up our project in `VScode` editor. It should look something like this.

<figure><img src="https://2394289113-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F4XnSsBH76iytbI7NwX5o%2Fuploads%2F8kO4NqVTZhHdS8Ad1Ma1%2Fboiler-plate.png?alt=media&#x26;token=987fd101-dbf6-4d3e-838b-3e6180f2fc95" alt=""><figcaption><p>The Visual Studio Code Editor</p></figcaption></figure>

### Connect Wallet and check module

Let's create a new module that will connect our wallet and check if one particular NFT is present in your wallet or not. We will need a few packages to get this module working. We have also used some of these modules in our previous projects, you can find the details [here](https://docs.shyft.to/tutorials/how-to-get-your-users-token-balances).

For connecting the wallet, we install and use the following packages,

```bash
npm install @solana/web3.js @solana/wallet-adapter-phantom
```

and we will need the following packages for making a network request.

```bash
npm install axios
```

Once done, let's create a react component for connecting the wallet. We will add a simple button that will connect the wallet and will get your wallet address. Once we have the wallet address, we will use [SHYFT APIs](https://https/shyft.to/) to get all the wallet NFTs for checking purposes. Please note that we have used very preliminary styling for our sample project, but you can add styles of your own if you want.

<figure><img src="https://2394289113-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F4XnSsBH76iytbI7NwX5o%2Fuploads%2FvAU91wy7sA7Z5OYwoSed%2Fconnect-wallet.png?alt=media&#x26;token=ce5273d7-73db-42ec-b68e-b494dcda0e10" alt=""><figcaption><p>Simple connect wallet button</p></figcaption></figure>

We create a function that we will use to connect a wallet, and we will execute this function when we click on the connect wallet. Before that, we create a few state variables using react's very own `useState` hook for storing the wallet address and checking if we have access to the portal or not.

```jsx
const [walletId,setWalletId] = useState(null);
const [hasAccess,setAccess] = useState(false);
```

Now we create the connect wallet function.

```javascript
const connectWallet = async () => {
    const { solana } = window;
    
    if(!solana)
    {
        alert("Please Install Phantom"); //If wallet Adapter not installed
    }
    try{  
        const network = "devnet";
        const phantom = new PhantomWalletAdapter();
        await phantom.connect();
        const rpcUrl = clusterApiUrl(network);
        const connection = new Connection(rpcUrl,"confirmed");
        
        const wallet = {
            address: phantom.publicKey.toBase58(), //getting the wallet id in base 58 format
        };

        if(wallet.address)
        {
            const accountInfo = await connection.getAccountInfo(new PublicKey(wallet.address),"confirmed");
            console.log(accountInfo); 
            console.log('Wallet Connected'); 
            setWalletId(wallet.address); //setting the wallet id using reacts setState.
        }

    }
    catch(err)
    {
        console.log(err);
    }
}
```

There are several other methods that can be used to connect wallets, we have used this one, but can use any method you feel like. You can even take the wallet address as an input field directly.

Once connected, we are ready to make our API call. We use react's `useEffect` hook to make the API call, and we add the `walletId` state variable as a dependency, so that the API call takes place whenever the `walletId` changes.

### The API call to fetch all NFTs

Before making the API calls, we will need the [`x-api-key`](https://shyft.to/get-api-key). We will need to pass `X-API-KEY` in the header, this key is used for authentication purposes.

You can find more about our APIs [here](https://docs.shyft.to/start-hacking/api-reference).

**Getting Your Own X-API-KEY**

`x-api-key` is an important parameter we pass on to the header while making the API call for authentication purposes. You can get your own `x-api-key` from our own [SHYFT website](https://shyft.to/get-api-key). Just signup with your email id [here](https://shyft.to/get-api-key) and you can get it for free.

Now, once we have the wallet address, we are ready to make the API call to fetch our required data which in this case is the token list.

To fetch the data, we have used the `axios` package, but you can use JavaScript's very own fetch or any other package you want. We have made this call inside React's `useEffect` hook. Here is the code.

Our API endpoint for reading al NFTs

```javascript
https://api.shyft.to/sol/v1/nft/read_all?network=devnet&address=wallet_address&update_authority=update_authority_of_the_nft&refresh=refresh`
```

```javascript
useEffect(() => {
        let nftUrl = `https://api.shyft.to/sol/v1/nft/read_all?network=devnet&address=${walletId}&update_authority=wallet_address_which_you_will_use_for_auth&refresh=refresh`;
        //add the wallet address which you want to check as an authentication parameter
        //access will be granted if and only if an NFT with this update authority is present in your wallet
        const xKey = 'your-x-api-key-from-shyft-website'

        axios({
          // Endpoint to get NFTs
          url: nftUrl,
          method: "GET",
          headers: {
            "Content-Type": "application/json",
            "x-api-key": xKey,
          },
        })
          // Handle the response from backend here
          .then((res) => {
            console.log(res.data);
            if (res.data.success === true) {
              setNfts(res.data.result);
              //or check the length of the nfts array over here,
              // if greater than zero, it will imply atleast one NFT with the 
              //required update_authority is present
            } 
          })
          // Catch errors if any
          .catch((err) => {
            console.warn(err);
            
          });
    
     
    }, [walletId]);
```

If the response from this API is true, we should have a response that looks somewhat like this.

```json
{
    "success": true,
    "message": "All NFTS in your wallet",
    "result": [
        {
            "name": "Girish",
            "symbol": "GN",
            "royalty": 5,
            "image_uri": "https://nftstorage.link/ipfs/bafybeidf3jfdczfu56knpfsqbcveks62xy44uognecz64kxvmaowqyg23q",
            "description": "Serial Entrepreneur ",
            "mint": "3iRECKHPvnfkH5wF6ZCTM4e9nULSevJJiCrxCfgG9eM7",
            "owner": "BvzKvn6nUUAYtKu2pH3h5SbUkUNcRPQawg4bURBiojJx",
            "attributes": {
                "girish": "true"
            },
            "update_authority": "BvzKvn6nUUAYtKu2pH3h5SbUkUNcRPQawg4bURBiojJx"
        },
        {
            "name": "Cool Monkry",
            "symbol": "CMY",
            "royalty": 5,
            "image_uri": "https://nftstorage.link/ipfs/bafkreie2ef3z2cixfnxby5zfprv2xa7lydy5biky34v2p2fgsb5b4mcfaa",
            "description": "Shyft makes web3 development so easy.",
            "mint": "BMv5StFwfJsXmMmehYATuytfhkmANvfhUHpu6YQHF1pX",
            "owner": "BvzKvn6nUUAYtKu2pH3h5SbUkUNcRPQawg4bURBiojJx",
            "attributes": {
                "edification": "100"
            },
            "update_authority": "BFefyp7jNF5Xq2A4JDLLFFGpxLq5oPEFKBAQ46KJHW2R"
        },
        {
            "name": "GUMBALL #247475",
            "symbol": "GUMBALL",
            "royalty": 1,
            "image_uri": "",
            "description": "Celebrate the new era of compressed NFTs",
            "mint": "6jhqJGJreGpQEP73ey5as7UBCzeRSWuLSM8m1V3pdBHb",
            "owner": "BvzKvn6nUUAYtKu2pH3h5SbUkUNcRPQawg4bURBiojJx",
            "attributes": {
                "Vibe Check": "Passed",
                "Solana Summer": "🔥 Started 🔥",
                "NFTs": "Compressed"
            },
            "update_authority": "2GDAzSBsMiS44gJzSEqH3APkabHGZcicNM9G7cmUo9hE"
        }
    ]
}
```

### NFT Access Check

If successful and the length of the `nfts` array is greater than 0, it would imply that we have at least one NFT whose `update_authority` is the wallet address which we are using for authentication (`update_authority` = `AagBXTi3HHFNMqTcWm3oYoQYSuUj1LGvb12vsPB` if `AagBXTi3HHFNMqTcWm3oYoQYSuUj1LGvb12vsPB` is the wallet address we are using for authentication). We can also perform checking on NFTs with specific attributes, and check if the user's wallet has one NFT with some specified value such as ***"health:50"*** or ***"Power: 100"***, or maybe an attribute as a password, for that we would need to iterate through the `nfts` array and check if any element of the array has an attribute.

```javascript
let flag = 0;
nfts.forEach((element) => {
  if (
    //check if element has an attribute that is equal to the attribute you are looking for authentication
  ) {
    flag = 1;
  }
});
if (flag === 1) {
    setAccess(true);
    //redirect user from here
} else {
    //dont redirect, and display the error message
    setAccess(false);
    setMsg('You do not have access');
}
```

Once authenticated we can redirect the user to our access portal.

<figure><img src="https://2394289113-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F4XnSsBH76iytbI7NwX5o%2Fuploads%2FlL7ZbzaC8hsiIK6KwRUo%2Fhave-access.png?alt=media&#x26;token=f68587df-b4a4-4e9b-9c45-847ffbb39846" alt=""><figcaption><p>Grant access to the portal if you have an NFT with the required update_authority in your wallet</p></figcaption></figure>

If the authentication fails, that is, if the user does not have the NFT in their wallet, we can give them an option to mint an NFT from another wallet, we hope to illustrate this soon in our more upcoming tutorials.

That is all regarding this sample project tutorial, where we see how we can use NFT as an access token to access a portal. If you enjoyed this tutorial and want to give our code a whirl, or make some contributions, here is a [link](https://github.com/Shyft-to/example-projects/tree/main/example-projects-on-NFTs/access-app) to this sample project.

Don't forget to experience the full flow [here](https://nft-as-access-token.vercel.app/).

<figure><img src="https://2394289113-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F4XnSsBH76iytbI7NwX5o%2Fuploads%2FaWXgYxstMstENdGPBrIu%2FScreenshot%20(547).png?alt=media&#x26;token=f8ddd23b-cac1-4c1e-a4eb-4a8964c98d39" alt=""><figcaption><p>Project on Ultility NFTs: How to use NFTs as access tokens</p></figcaption></figure>

### Resources

* [SHYFT API Documentation](https://docs.shyft.to/)
* [Shyft Website](https://shyft.to)
* [Get API Key](https://shyft.to/get-api-key)
* [Github](https://github.com/Shyft-to)
* Join our [Discord](https://discord.com/invite/VS5ThWVRMn)

If you liked this, you can also read our tutorials on [How to get your user's token balances?](https://docs.shyft.to/dev-guides/solana/fungible-tokens/how-to-get-token-balances) or [Read all NFTs from a wallet](https://docs.shyft.to/tutorials/read-all-nfts-from-a-wallet).

Hope you have a great time building Dapps with [SHYFT](https://shyft.to/) APIs. Happy Hacking!! :innocent:


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.shyft.to/tutorials/build-nft-gated-dapp.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
