Building an Aavegotchi DApp using React + Web3
Tags: react, web3, aavegotchi, dapp
Published: 2021-04-20 06:42:43

Welcome fren! In this tutorial, I will be guiding you through the process of building a DApp (decentralised app) that is connected to the Aavegotchi blockchain. The tutorial will be in React and Typescript, however, don't worry if you do not have any React experience as the real meat of the tutorial is using Web3 and the Aavegotchi Subgraph.

You can find the completed code here:
[https://github.com/cgcbrown/aavegotchi-dex-tutorial](https://github.com/cgcbrown/aavegotchi-dex-tutorial)


### What is Web3?

When developing an app on the blockchain, there are 2 sides to it.
1. Smart contract development - writing code that gets deployed to the blockchain with the Solidity programming language.
2. Developing websites or clients that interact with the blockchain via smart contracts.

As the Aavegotchi smart contract is already deployed on the Matic network, all we have to worry about is using Web3 to fulfil the second responsibility. Essentially you can think of Web3 as an API for the blockchain where all you need is the address of the smart contract, an ABI and a Provider.

### What is the Aavegotchi Subgraph?

The Subgraph is a GraphQL API built by the Pixelcraft team on [The Graph](https://thegraph.com/) that allows you to more efficiently get data from the Aavegotchi blockchain without having to worry about any Web3 setup. It is useful for viewing data from the contract, however, it has its limitations. You cannot call methods that require gas (like petting your Aavegotchi) and some data that you want may not be integrated into the subgraph yet.

&nbsp;

# The Build

For this tutorial, we are going to build an Aavegotchi Pokédex that allows the user to search and view all of the summoned Aavegotchis. The end result will look something like this:

![Final result](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r8spqj98g24y14h8yqsz.png)

### Initial setup

Before you can start you will need to make sure you have `node >= 10.16` and `npm >= 5.6` installed on your machine. You will also need an Ethereum compatible browser (if you are using Chrome or Firefox you will need to install the Metamask browser extension) connected to the Matic Network.

Now that is done, let us create our React app. To do this, open up your terminal, and run the following lines:

```
mkdir tutorials
cd tutorials
npx create-react-app aavegotchi-dex --template typescript
```
This will build a react app for you called `aavegotchi-dex` inside a newly created directory called tutorials. using `--template typescript` configures the React app to use Typescript.

After it's done installing, in your terminal run:
```
cd aavegotchi-dex
npm start
```
This should automatically open up your browser and you should see your app running on `localhost:3000/`. If not open up your browser and manually put `http://localhost:3000/` in the address bar.

![create-react-app default screen](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fwzaonxpkjmy5m8b9td7.png)

Now in your code editor of choice (I personally use Visual Studio code) open up `aavegotchi-dex`

In `src/App.tsx` replace all the code with the following and save:

```jsx
//App.tsx

import { useEffect } from 'react';
import './App.css';
 
function App() {

 const fetchGotchis = () => {
   console.log('Hello fren');
 }
 
 useEffect(() => {
   fetchGotchis();
 }, [])
 
 return (
   <div className="App">
   </div>
 );
}
 
export default App;
```

Your screen in the browser should now be blank. However, if you open up your dev tools in the browser, you should see `Hello fren` in the console.

This isn’t a React tutorial, so don't worry if you don't fully understand what is happening. All you need to know is when the component is rendered, the `useEffect()` hook is triggered which in turn is triggering the `fetchGotchis()` function. This is where we are going to put our logic to fetch the Aavegotchi logic from the blockchain.
&nbsp;

## Using the Aavegotchi Subgraph

Now with the boring bits out of the way, let us start pulling in data from the blockchain!

### The Subgraph

To make our lives easier we can use the Aavegotchi Subgraph to pull in our list of Aavegotchi's data. What's handy about the subgraph is you can open up the playground [here](https://thegraph.com/explorer/subgraph/aavegotchi/aavegotchi-core-matic) to get your graphQL query before even writing any lines of code.

![Aavegotchi Core Matic Subgraph](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vynusyz5r9c6iiagjv1t.png)

On the right, there is a Schema that allows you to visualise the data we can fetch.

> The subgraph has a hard limit of 1000 on the amount of data you can fetch with a single query. This is not a problem as for performance reasons we will fetch 100, and then later, you can add the ability to fetch more data as you scroll.

We can now pick and choose what data we want to be returned from the query. For the Aavegotchidex we know we want the:
- name
- id
- collateral
- numeric traits

![TheGraph query and response](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sfawiehw9rdx7j3kunpf.png)
> We are ordering the data by `gotchiId` instead of `id` because `gotchiId` is numeric. Try ordering it by `id` and you will see why this is important.

So how come we also aren’t getting the SVG data? Well if you look at the Aavegotchi schema you will see that there is no corresponding property for the SVG (at the time of writing this tutorial that is). This is an example of where we will be using *Web3* later.

### Using our query in React

Now that we have our query let's use it in our app. For this, we need to install 2 packages, `graphQL` and `graphql-request` as our graphQL client. So open up a new terminal, and inside your `aavegotchi-dex` directory run:
```
npm install graphql-request graphql
```

Once they have installed, in `App.tsx` put in the following new lines of code

```jsx
//App.tsx

import { useEffect } from 'react';
import { request } from "graphql-request"; // <-- New line
import './App.css';
 
const uri = 'https://api.thegraph.com/subgraphs/name/aavegotchi/aavegotchi-core-matic';

function App() {

// Make sure this function is now Asynchronous
const fetchGotchis = async () => {
   const query = `
   {
     aavegotchis(first: 100, orderBy: gotchiId) {
       id
       name
       collateral
       withSetsNumericTraits
     }
   }
 `
 const response = await request(uri, query);
 console.log(response);
}
...
```
>If you are getting a Typescript runtime error, run `npm install @types/react --dev`.

If you have done everything correctly you should now see the aavegotchi data logged in your console exactly as you requested it. So what's happening?

Well, the imported request function requires 2 arguments, the target *URL* and the *query*. We get the URL from [thegraph.com](https://thegraph.com/explorer/subgraph/aavegotchi/aavegotchi-core-matic) under Queries (HTTP), this tells the GraphQL request where to target.

The query is what we mocked up earlier and have now converted into a string. We then asynchronously waited for the response to return and logged it in the console.

Now that we know our request works, we need to store it in the Apps state so we can display it in the UI. For this, we use a React hook called `useState()`. However, because we are using Typescript we need to first set up our interface.

Let us create a new folder under `src` called `types` and inside create an `index.ts` file. Now in `src/types/index.ts` put in the following code:

```javascript
//types/index.ts

export interface Gotchi {
 collateral: string;
 id: string;
 name: string;
 withSetsNumericTraits: Array<Number>;
}
 
export interface QueryResponse {
 aavegotchis: Array<Gotchi>
}
``` 
Again, I'm not going to go over what the syntax of the Typescript means. You just need to understand that we are copying what we expect the response to look like from our Subgraph query.

Now at the top of `App.tsx` import our types and the `useState` hook from React, and edit the `fetchGotchis` function to store the response in the state:

```javascript
//App.tsx

import { useEffect, useState } from 'react';
import { Gotchi, QueryResponse } from './types';
...

function App() {
  const [ gotchis, setGotchis ] = useState<Array<Gotchi>>([]);

  const fetchGotchis = async () => {
    const query = `
      {
        aavegotchis(first: 100, orderBy: gotchiId) {
          id
          name
          collateral
          withSetsNumericTraits
        }
      }
    `
    const response = await request<QueryResponse>(uri, query);
    setGotchis(response.aavegotchis)
  }
  ...
}
```

Now that we have stored the data, we can map it onto the screen. If you type this out manually within the `App` components return function you will be able to see Typescript coming into play and suggesting properties for you. It will also flag up any mistypes (the amount of time this will save you from bug fixing is dreamy).

```jsx
//App.tsx

return (
  <div className="App">
    {gotchis.map((gotchi, i) => {
      return (
        <p key={i}>{gotchi.name}</p>
      )
    })}
  </div>
);
```

We should now see a list of names on the screen.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ylyvx8x3ku1lsxu4r2ti.png)

However, this doesn't look very interesting. So what we are gonna do is create a new component for the Aavegotchi listing, that allows you to select an Aavegotchi.
&nbsp;

## Structuring our code

In `App.tsx` replace the returned JSX with the following code:
```jsx
//App.tsx

return (
  <div className="App">
    <div className="container">
      <div className="selected-container">
      </div>
      <div className="gotchi-list">
      </div>
    </div>
  </div>
);
```
and inside `App.css` replace the CSS with:
```css
.App {
 display: block;
 text-align: center;
 height: 100vh;
 background-color: #FA34F3;
 box-sizing: border-box;
}
 
.container {
 display: grid;
 grid-template-rows: 50% 50%;
 box-sizing: border-box;
 height: 100%;
 width: 100%;
}
 
.gotchi-list {
 background-color: white;
 border-left: 5px solid black;
 border-right: 5px solid black;
 height: 100%;
 overflow-x: hidden;
 overflow-y: scroll;
 box-sizing: border-box;
}
 
@media (min-width: 768px) {
 .container {
   max-width: 1300px;
   margin: 0 auto;
   grid-template-columns: 1fr 1fr;
   grid-template-rows: revert;
 }
 .selected-container {
   box-sizing: border-box;
   padding: 16px;
   height: 100%;
 }
}
```

We now want to create a new component for each Aavegotchi listing as well as for the selected Aavegotchi.

So within `src` create a new folder called `components` and inside create two more folders called `GotchiListing` and `SelectedGotchi` which both have an `index.tsx` and a `styles.css` file.

Your folder structure should now look like this:
![Folder structure](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sk188ul7rrde2431pc6t.png)

#### Render our Aavegotchi listing

Inside `GotchiListing/index.tsx` copy and paste in the following content:

```jsx
//GotchiListing/index.tsx

import "./styles.css"

interface Props {
  id: string;
  name: string;
  collateralColor: string;
  selected: boolean;
  selectGotchi: () => void;
}

export const GotchiListing = ({ id, name, collateralColor, selected, selectGotchi }: Props) => {
 return (
   <div className={`gotchi-listing ${selected && 'selected'}`} onClick={() => selectGotchi()}>
     <div className="collateral-container">
       <div className="collateral" style={{ backgroundColor: collateralColor }} />
       </div>
     <p className="id">{id}</p>
     <p className="name">{name}</p>
   </div>
 )
}
```

The interface tells the editor that the GotchiListing component expects the following properties:
- name - *Name of the Aavegotchi*
- Id - *Id of the Aavegotchi*
- collateralColor - *Primary color of the collateral (more on this later)*
- selected - *boolean of whether the item is selected or not*
- selectGotchi - *Function that passes the click event to the parent*

Inside `GotchiListing/styles.css` put:

```css
.gotchi-listing {
  display: flex;
  cursor: pointer;
}
.gotchi-listing.selected,
.gotchi-listing:hover {
  background-color: #fffa65;
}

.collateral-container {
  width: 54px;
  display: grid;
  place-items: center;
}

.collateral {
  width: 32px;
  height: 32px;
  border-radius: 50%;
}

.id {
  padding-right: 12px;
  width: 60px;
  text-align: right;
}

.name {
  text-transform: uppercase;
  white-space: nowrap;
  text-overflow: ellipsis;
  overflow: hidden;
}
```

Now inside `App.tsx` lets import in and render our new component!

At the top with the other imports put:
```javascript
//App.tsx

import { GotchiListing } from './components/GotchiListing';
```

And inside the div with a className of `gotchi-list` we should map out our `<GotchiListing />` component for each Aavegotchi stored in our state:

```jsx
//App.tsx

<div className="gotchi-list">
  {
     gotchis.map((gotchi, i) => (
       <GotchiListing
         key={gotchi.id}
         id={gotchi.id}
         name={gotchi.name}
         collateralColor="black"
         selectGotchi={() => null}
         selected={false}
       />
     ))
   }
</div>
```
> If you are getting a run time error, inside `SelectedGotchi/index.tsx` type and save `export {}` as a temporary fix.

By doing this you should now be able to scroll through the list of Aavegotchis.

![Gotchi list displaying](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yktb624g43e7c3mjmsbi.png)

>You may have noticed that we are not passing the `gotchi.collateral` to the `collateralColor`. That's because the collateral we get returned isn't a hex code, but a unique ID for the collateral. We will have to use *Web3* later to call the aavegotchi contract to receive what the corresponding color should be.
&nbsp;

#### Selecting an Aavegotchi

Time to put in our selection logic. First, we create another state within `App.tsx` for the selected Aavegotchi's index:

```javascript
//App.tsx

const [ selectedGotchi, setSelectedGotchi ] = useState<number>(0);
```

Now when we click on a listing, we want to set the index position of the selected gotchi inside the state. And then we can use that information to check whether a listed gotchi is selected or not:

```jsx
//App.tsx

<GotchiListing
  ...
  selectGotchi={() => setSelectedGotchi(i)}
  selected={i === selectedGotchi}
/>
```

Great! When you click a listing you should now see the listing is highlighted.

Now let us display the selection in a new component called SelectedGotchi. Inside `SelectedGotchi/index.tsx` paste in the following code:

```jsx
//SelectedGotchi/index.tsx

import './styles.css'

interface Props {
 name: string;
 traits: Array<Number>;
}

export const SelectedGotchi = ({ name, traits }: Props) => {
  return (
    <div className="selected-gotchi-container">
      <div className="name-container">
        <h2>{name}</h2>
      </div>
      <div className="svg-container" />
      <div className="traits-container">
        <div className="trait">
          <p>⚡ Energy</p>
          <p>{traits[0]}</p>
        </div>
        <div className="trait">
          <p>👹 Aggression</p>
          <p>{traits[1]}</p>
        </div>
        <div className="trait">
          <p>👻 Spookiness</p>
          <p>{traits[2]}</p>
        </div>
        <div className="trait">
          <p>🧠 Brain size</p>
          <p>{traits[3]}</p>
        </div>
        <div className="trait">
          <p>👀 Eye shape</p>
          <p>{traits[4]}</p>
        </div>
        <div className="trait">
          <p>👁 Eye color</p>
          <p>{traits[5]}</p>
        </div>
      </div>
    </div>
  )
}
```

Inside `SelectedGotchi/styles.css`:

```css
.selected-gotchi-container {
  display: grid;
  grid-template-rows: 15% 35% 50%;
  width: 100%;
  height: 100%;
  max-height: 100%;
}

.name-container {
  display: grid;
  place-items: center;
  border: 5px solid #e5df40;
  background-color: #fffa65;
  text-transform: uppercase;
}
.name-container h2 {
  margin: 0;
}

.svg-container {
  display: grid;
  place-items: center;
}
.svg-container > svg {
  height: 100%;
}

.traits-container {
  padding: 0.4rem;
  background-color: white;
  border: 5px solid black;
  display: grid;
  grid-template-columns: 1fr 1fr;
  row-gap: 12px;
  column-gap: 16px;
}
.trait {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.trait p {
  margin: 0;
  text-transform: uppercase;
}

@media (min-width: 768px) {
  .selected-gotchi-container {
    grid-template-rows: 72px 1fr 170px;
  }

  .svg-container > svg {
    height: revert;
    max-height: 450px;
  }

  .traits-container {
    padding: 1.6rem;
  }
}

```

Now we render our new component in `App.tsx` like so:

```jsx
//App.tsx

...

import { SelectedGotchi } from './components/SelectedGotchi';

...
 
function App() {

 ...
 
 return (
  <div className="App">
    ...
      <div className="selected-container">
        {gotchis.length > 0 && (
          <SelectedGotchi
            name={gotchis[selectedGotchi].name} 
            traits={gotchis[selectedGotchi].withSetsNumericTraits}
          />
        )}
      </div>
      ...
  </div>
 );
}
 
export default App;
```

What we are doing is checking if any gotchis' exist in the array, then we're rendering in our `<SelectedGotchi />` component. We then use the `selectedGotchi` index to get the target gotchis name and traits from the `gotchis` array. 

You should now be able to select a gotchi and see the name and traits change in our new component!

![Selected gotchi component](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k7ea7j0f2bzk0ekqutq4.png)

Great! Well done for making it this far, for the final part of the tutorial we will be using *Web3* to fetch the data that we couldn't get from the subgraph.
&nbsp;

## Using Web3

To view information on the blockchain you need 3 things:

1. **A provider**
The provider is your choice of the node which talks to the Matic Network. If you have Metamask installed or are you using an Ethereum compatible browser then that will be used as your line of communication.

2. **The smart contracts address**
This is essentially the URL of the target smart contract, we can find what this is by going on the [Aavegotchi Contracts GitHub](https://github.com/aavegotchi/aavegotchi-contracts) for the contracts.
We want the Aavegotchi diamond address as it has access to all the facets we need.

3. **The ABI (application binary interface)**
This is a JSON file whose job is to encode and decode the calls to and from the Solidity contract. We also can download/copy this from the Aavegotchi Github [here](https://github.com/aavegotchi/aavegotchi-contracts/blob/master/diamondABI/diamond.json).

Once we have located everything we need, we can start using it within our App.

### Setting up the contract

Let us start by installing `web3`:
```
npm install web3
```
Now within the `src` folder of our app lets create a new folder called `abi` and inside it create a JSON file called `diamondABI.json`. In this file, we want to copy and paste the whole JSON object from the [Github](https://github.com/aavegotchi/aavegotchi-contracts/blob/master/diamondABI/diamond.json).

Inside `App.tsx` we can now import the following:
```javascript
//App.tsx

import Web3 from 'web3';
import diamondABI from './abi/diamondABI.json';
import { Contract } from 'web3-eth-contract';
import { AbiItem } from 'web3-utils/types'

const diamondAddress = '0x86935F11C86623deC8a25696E1C19a8659CbF95d';
```
> `Contract` and `AbiItem` are used only for Typescript purposes.

We also set the `diamondAddress` as a const using the address we found in the Aavegotchi Contract Github.

Now we have everything we need to view data from the Aavegotchi Blockchain. Inside `App()` let's create a new function called `connectToWeb3()` that will create our contract and save it in our state.

We want to call this function when the page first renders, therefore we put it in the `useEffect()` after `fetchGotchis()`.

```javascript
// App.tsx

function App() {
  ...
  const [ contract, setContract ] = useState<Contract | null>(null);

  const connectToWeb3 = () => {
    const web3 = new Web3(Web3.givenProvider);
    const aavegotchiContract = new web3.eth.Contract(diamondABI as AbiItem[], diamondAddress);
    setContract(aavegotchiContract);
  }

  ...

  useEffect(() => {
    fetchGotchis();
    connectToWeb3();
  }, [])
```
For the provider we have used `Web3.givenProvider`, this is automatically available if you are using an Ethereum compatible browser. If you don't have an Ethereum compatible browser then instead you can set up a remote or local node and use that as your provider.

### Calling methods from the contract

Now that our contract is set up we can start calling methods off of it. You may be aware that calling methods on a contract may require gas. However, this only applies to methods that have to add, delete or change information on the contract. Just viewing data requires no manipulation of the contract and is therefore completely gas-free!

The first method we want to call is one to fetch the *collateral primary colors* so we can pass each `<GotchiListing />` the correct color. By visiting the [Aavegotchi Developer Documentation](https://docs.aavegotchi.com/) you can find the methods names for the various contracts. We want the `getCollateralInfo()` function as located [here](https://docs.aavegotchi.com/diamond-facets/collateralfacet.sol).

> You can also find all of the contracts functions as well as their outputs and inputs within the ABI!

We want to fetch all of the *collateral information* in one request, however, we need to make sure that the `contract` is set up first.

To do this, create a new `useEffect()` hook within `App.tsx` which has the `contract` as a dependency:

```javascript
//App.tsx

useEffect(() => {
  if (!!contract) {
    const fetchAavegotchiCollaterals = async () => {
      const collaterals = await contract.methods.getCollateralInfo().call();
      console.log(collaterals);
    };
    fetchAavegotchiCollaterals();
  }
}, [contract]);
```

As you can see, the `fetchAavegotiCollaterals()` function will only be triggered if `contract` is truthy. Therefore on initial render, it will not trigger as the contract wouldn't be set up yet. Therefore by adding contract as a dependency, `useEffect()` will now trigger as a side effect to the `contract` changing.

If everything has been put in correctly you should now see the different collaterals logged in your browser's console.

![Logged collaterals](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zi5t25g603bdcc1buqie.png)

We can use the logged output to create our type definition so our code editor knows what we are expecting. So inside `src/types/index.ts` let's create a new interface for `Collateral` like so:

```typescript
// types/index.ts

export interface Collateral {
  collateralType: string;
  collateralTypeInfo: {
    cheekColor: string;
    conversionRate: string;
    delisted: boolean;
    eyeShapeSvgId: string;
    modifiers: Array<string>;
    primaryColor: string;
    secondaryColor: string;
    svgId: string;
  }
}
```

In `App.tsx` lets import our new interface and create a new state which expects an array of collaterals and in our `fetchAavegotchiCollaterals()` function we can set the state:

```jsx
//App.tsx

function App() {
  ...
  const [ collaterals, setCollaterals ] = useState<Array<Collateral>>([]);
  ...

 useEffect(() => {
  if (!!contract) {
    const fetchAavegotchiCollaterals = async () => {
      const collaterals = await contract.methods.getCollateralInfo().call();
      setCollaterals(collaterals); // <- Replaced console.log()
    };
  
    fetchAavegotchiCollaterals();
  }
}, [contract]);

```

We should now have all the collaterals stored in the state, so let's create a function that takes the `gotchi.collateral`, finds it within `collaterals` and returns the corresponding `primaryColor`.

```jsx
//App.tsx

function App() {

  ...

  const getCollateralColor = (gotchiCollateral: string) => {
    const collateral = collaterals.find(item => item.collateralType.toLowerCase() === gotchiCollateral);
    if (collateral) {
      return collateral.collateralTypeInfo.primaryColor.replace("0x", '#');
    }
    return "white";
  }

  ...
 
  return (
    <div className="App">
        ...
        <div className="gotchi-list">
          {
            gotchis.map((gotchi, i) => (
              <GotchiListing
                ...
                collateralColor={getCollateralColor(gotchi.collateral)}
                ...
              />
            ))
          }
        </div>
        ...
    </div>
  );
}
```
> The replace operation correctly formats the `primaryColor` value into a hex code that the CSS can interpret.

Your gotchi listing should now have the color that represents the gotchis collateral (If you wanted to go a step further you could see if you can put in the logic to display the correct collateral icon).

![Collateral colors in listings](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k8bo8jx53q3oq0ppjak8.png)
&nbsp;

## Displaying the Aavegotchi SVG

All we have left to do is display the selected Aavegotchis image. This is arguably my favourite thing about Aavegotchi as all the SVG’s are stored within the blockchain itself!

If you go back to the [Aavegotchi developer wiki](https://docs.aavegotchi.com/diamond-facets/svgfacet.sol) you can locate the method we want, which is `getAavegotchiSvg(tokenId)`. This method requires passing an Aavegotchis Id as a parameter.

> Since writing this tutorial, the Aavegotchi's side and back SVG's are also available via calling `getAavegotchiSideSvgs(tokenId)`. This will return an Array of each SVG.`

Every time we select a gotchi we want to render the SVG within our SelectedGotchi component. Therefore we need a new `useEffect()` hook that will trigger every time `selectedGotchi`, `gotchis` or `contract` changes:

```javascript
//App.tsx

function App() {
  ...
  const [ gotchiSVG, setGotchiSVG ] = useState<string>('');

  ...

  useEffect(() => {
    const getAavegotchiSVG = async (tokenId: string) => {
      const svg = await contract?.methods.getAavegotchiSvg(tokenId).call();
      setGotchiSVG(svg);
    };

    if (contract && gotchis.length > 0) {
      getAavegotchiSVG(gotchis[selectedGotchi].id)
    }
  }, [selectedGotchi, contract, gotchis]);

```

> If you were to `console.log(gotchiSVG)` you would see that the output is HTML code. This is the SVG data that we want to inject into our code.

We then pass the SVG data into our `<SelectedGotchi />` component like so:

```jsx
//App.tsx

<SelectedGotchi
  svg={gotchiSVG}
  name={gotchis[selectedGotchi].name} 
  traits={gotchis[selectedGotchi].withSetsNumericTraits}
/>
```

Within the SelectedGotchi component, we need to add the `svg` property to the interface so we can use it as a prop.

So go to `src/components/SelectedGotchi/index.tsx` and add the following changes:
```jsx
// SelectedGotchi/index.tsx

import './styles.css'

interface Props {
  name: string;
  traits: Array<Number>;
  svg: string; //<-- New prop
}

export const SelectedGotchi = ({ name, traits, svg }: Props) => {
  return (
    <div className="selected-gotchi-container">
      ...
      <div className="svg-container" dangerouslySetInnerHTML={{ __html: svg }} />
      ...

 ```

If everything is done correctly you should now be able to see your selected Aavegotchi!

![Aavegotchi SVG displaying](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t6ik4pcqqcvw6a2ozo0s.png)

As the SVG data is being rendered in the DOM you can use your browsers element inspector to identify the class names of the different layers of the SVG. This is useful if you want to animate or hide certain layers of the Aavegotchi SVG.

To show this we are going to hide the SVG background by pasting into `SelectedGotchi/styles.css`:

```css
.svg-container .gotchi-bg,.wearable-bg {
  display: none;
}
```

The background should now be hidden!

![Aavegotchi background hidden](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ltj1hujuk1cy9vkj9k5d.png)
&nbsp;

## Conclusion

Nice one fren! In this tutorial, you have learnt how to use both the *Subgraph* and *Web3* to create a decentralised React App!

You should now be equipped with the knowledge you need to take the app a step further. You could add in an infinite scroll that concats more Aavegotchi data into the listing... Or perhaps some filter or sorting functionality that sends a new query to the subgraph to fetch more data?

If you have any questions about Aavegotchi or want to build more DApps, then join [Aavegotchi discord community](https://discord.com/invite/NPwnWB6) where you will be welcomed with open arms!

&nbsp;

You can find the completed code here:
[https://github.com/cgcbrown/aavegotchi-dex-tutorial](https://github.com/cgcbrown/aavegotchi-dex-tutorial)