# Creating a Decentralised Crowd Funding Contract with Solidity - Part 2: Creating a subgraph

This is the second article of the  "Creating a Decentralized Crowdfunding Contract with Solidity" series. 

In this section, we'll make a subgraph for our smart contracts. We will use The Graph Protocol's tooling and build a subgraph from scratch to index data from the `CrowdFundingContract`. You can find the first installment of the series [here](https://blog.developerdao.com/creating-a-decentralised-crowd-funding-contract-with-solidity)


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

## Brief Intro to The Graph
The Graph is a decentralized protocol for indexing and querying data from Ethereum-based blockchains. It allows you to query data that is otherwise difficult to query directly. [TheGraph](https://thegraph.com/) is like the Google of the decentralized world. The Graph indexes smart contract data to IPFS and makes this data easily searchable with GraphQL. In this post, we will create a subgraph for the `CrowdFundingContract` to index the events generated by the contract.

Before proceeding further, we will need to install the graph CLI on our development machine if we have not done that before. Open a terminal on your machine and type the command below to install the CLI:

```
yarn global add @graphprotocol/graph-cli
```

Using npm:

```
  npm install -g @graphprotocol/graph-cli
```
Check if the installation succeeds by typing:

```
  graph -v
```

## Project Setup and Installation

The Graph operates a hosted service where we can deploy our subgraph. To get started, navigate to [thegraph.com](https://thegraph.com) and sign in using your GitHub account.

Proceed to the "My Dashboard" tab and click the button "Add a subgraph." Fill in the required fields and click the “Create subgraph”  button. 

Navigate to where you want to place the subgraph on your computer and type the command 

```
  graph init --product hosted-service <GITHUB_USER>/<SUBGRAPH_NAME>
```
Replace `<GITHUB_USER>` with your GitHub username and `<SUBGRAPH_NAME>` with the name of the subgraph created. For example, if your GitHub username is `bluecoding` and the name of the subgraph is `fundingsubgraph`, then your graph init command will be:

```
  graph init --product hosted-service bluecoding/fundingsubgraph
```

Next, select Ethereum as the protocol on which we will build the subgraph and give the subgraph a name.

Select the directory where the subgraph is created.

On the Ethereum network, select the network that the `CrowdFundingContract` is deployed. I deployed mine to the Goerli, so I picked `goerli`.

The next step is to enter the contract address. This will be the contract address of the factory contract used to create clones of the 'CrowdFundingContract' in our case. 

> Note: In the first series, we had two contracts: the `CrowdSourcingFactory` (factory contract) and the `CrowdFundingContract` (implementation contract). The factory clones the implementation contract to produce a child crowdfunding contract.


The CLI tool will try to retrieve the contract's ABI from Etherscan. If the fetch fails, you should manually copy the ABI and point to the directory where it is stored.

Next, we enter the contract's name, `CrowdSourcingFactory` (factory contract). 

> Note: you can’t have spaces or dashes in the contract name, or the setup will fail.

The CLI installs all dependencies, and we are ready to build the subgraph. 


## Subgraph Folder Structure


![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1666334566156/JD7mf3tMD.png align="left")

### The `schema.graphql` File

We will define a schema within this file that will represent the shape of the data we want to save from our events. We want to save the data of anyone who has donated to a campaign as well as the data of those who created a campaign in the `CrowdFundingContract`.

### Entity and Relationship Type Definition

The data model or shape created is called an `Entity`. An `Entity` may have relationships with one another. We have one-to-one entity relationships, one-to-many entity relationships, and many-to-many entity relationships. 

A one-to-one entity relationship exists where each row, for example, entity A has a relationship with precisely one other row in entity B. For example, a person can only have one birth certificate.

```
  //sample birth certificate entity
  type BirthCertificate @entity {
  id: ID!
  SSN: String!
  DateOfBirth: BigInt!
}
```

> Note: A field defined with an `!` at the end means the field can not be `null`.

```
//sample person entity
 type Person @entity {
    id: ID!
    name: String!
    birthCertificate: BirthCertificate
 }
```
We can see above that a `Person` entity has a one-to-one relationship with a `BirthCertificate` entity. The `birthCertificate` field of the `Person` entity represents a `BirthCertificate` entity.

One-to-many relationships exist between entities where one record of Entity A has a reference with many records of entity B. A person can create many contracts. 

```
//contract
type Contract @entity {
  id: ID
   address: ID!
  creator: Person!
}
```

```
//person
type Person @entity {
  id: ID
  name: String!
  createdContracts: [Contract!] @derivedFrom(field: "creator")
}
```

In this example, a `Person` entity can create multiple contracts. The many-side of the relationship is the `Person` entity. When saving the relationship, we only keep one-side of the relationship, which is that of the `Contract` entity. A reverse lookup query will derive the many-side. The general rule is to store the entity on one-side and derive the many-side.

### Crowdfunding Contract Schema Definition

Delete the content of the `schema.graphql` file and replace it with the following content

```
  enum MilestoneStatus {
  Approved
  Declined
  Pending
}

type CampaignCreator @entity {
  id: ID!
  createdCampaigns: [Campaign!] @derivedFrom(field: "owner")
  fundingGiven: BigInt
  fundingWithdrawn: BigInt
}

type Campaign @entity {
  id: ID!
  campaignCID: String!
  details: String
  milestone: [Milestone!] @derivedFrom(field: "campaign")
  currentMilestone: ID
  dateCreated: BigInt!
  campaignRunning: Boolean!
  owner: CampaignCreator!
  amountSought: BigInt!
  donors: [Donors!] @derivedFrom(field: "campaign")
}

type Milestone @entity {
  id: ID!
  milestoneCID: String!
  details: String
  campaign: Campaign!
  milestonestatus: MilestoneStatus!
  periodToVote: BigInt!
  dateCreated: BigInt!
}

type Donors @entity {
  id: ID!
  campaign: Campaign!
  amount: BigInt!
  donorAddress: Bytes!
  date: BigInt!
}

```

We define a schema with the data type that will be indexed and queried later. So,
we have defined four entity types `CampaignCreator`, `Campaign`, `Milestone`, and `Donors`. 

> Note: After creating the schema, we run on the project's terminal `yarn run codegen` or `npm run codegen` to generate entity types from the schema for use in the `mapping.ts` file.

#### The `CampaignCreator` Entity

The `CampaignCreator` entity saves details about the person that creates the crowdfunding campaign. Remember that using the factory contract, anyone can create a `CrowdFunding` contract. It has fields:


* `id`: type `ID` and is a primary key that cannot be `null`.
* `createdCampaigns` : a derived field of `Campaign` entity. 
* `fundingGiven`: this is of type `BigInt`, which tracks the amount of funding a creator has received.
* `fundingWithdrawn`: type `BigInt`, and it tracks the amount a creator has withdrawn


#### The `Campaign` Entity

The `Campaign`entity saves details for each fundraising campaign created. It has and tracks the following fields:

* `id` primary key of the entity and not nullable
*  `campaignCID`: type String. We use it to save the IPFS content hash of the campaign details
* `details`: type String and saves the details about what the crowdfunding campaign is for. Since keeping data on-chain is very expensive, the details of a campaign are held off-chain. Only the IPFS hash of the campaign details is saved on-chain.
* `milestone`: this is a derived field from the `Milestone` entity. It keeps track of all the milestones created for the campaign. Remember, a milestone is created and voted on before a creator can withdraw funds.

* `currentMilestone`: type `ID`. The current active milestone of a campaign.
*  `dateCreated`: type `BigInt` and non nullable.
* ` campaignRunning` type `Boolean` and cannot be null.
* `owner`: type `CampaignCreator`. The one-side of the relationship.
* ` amountSought`: of type `BigInt` and can't be `null`. The campaign amount sought.
* `donors`: type `Donor`. A derived field, resolved by a reverse lookup. 


#### The `Milestone` Entity

This entity tracks the `Milestone` created for a campaign. A campaign creator can withdraw funds three times according to the logic defined in the contract. The fields of the `Milestone` entity are:

* `id`: type `ID`
* `milestoneCID`: the hash of the milestone details stored on IPFS
* `details`: the details of the milestone
* `campaign` : type `Campaign`. The campaign the milestone is for.
* `milestonestatus`: this is an ènum`of type `MilestoneStatus` with values of `approved`, `pending`, and `rejected`.
* `periodToVote`: type BigInt. It saves value for the period to vote.
* `dateCreated`: type BigInt. The creation date of the milestone.

#### The `Donors` Entity

The `Donors` entity saved donors to a campaign. The fields are enumerated below:

* `id` : type `ID`. Primary non-nullable field
*  `campaign`: type `Campaign`. The `campaign the donor is donating to.
* `amount`: type BigInt. The amount the person is donating.
* `donorAddress`: type `Bytes`. The wallet address of the donor
* `date`: type `BigInt`: the date of the donation.

## The `subgraph.yaml` File

This file is a configuration file. It contains information about the contract we are indexing. Open the `subgraph.yaml` file and notice that some details are already filled in for us. We are going to make some edits to this file. The CLI used the provided ABI to auto-fill the file.

```
//subgraph.yaml file content
specVersion: 0.0.4
schema:
  file: ./schema.graphql
features:
  - ipfsOnEthereumContracts
dataSources:
  - kind: ethereum/contract
    name: CrowdSourcingFactory
    network: goerli
    source:
      address: "0xeB1F85B8bc1694Dc74789A744078D358cb88117f"
      abi: CrowdSourcingFactory
      startBlock: 7763910
    mapping:
      kind: ethereum/events
      apiVersion: 0.0.6
      language: wasm/assemblyscript
      entities:
        - CampaignCreator
        - Campaign
        - Milestone
        - Donors
      abis:
        - name: CrowdSourcingFactory
          file: ./abis/CrowdSourcingFactory.json
      eventHandlers:
        - event: newCrowdFundingCreated(indexed address,uint256,address,string)
          handler: handlenewCrowdFundingCreated
      file: ./src/mapping.ts
templates:
  - kind: ethereum/contract
    name: CrowdFundingContract
    network: goerli
    source:
      abi: CrowdFundingContract
    mapping:
      kind: ethereum/events
      apiVersion: 0.0.6
      language: wasm/assemblyscript
      file: ./src/mapping.ts
      entities:
        - CampaignCreator
        - Campaign
        - Milestone
        - Donors
      abis:
        - name: CrowdFundingContract
          file: ./abis/CrowdFundingContract.json
        - name: CrowdSourcingFactory
          file: ./abis/CrowdSourcingFactory.json
      eventHandlers:
        - event: fundsDonated(indexed address,uint256,uint256)
          handler: handleFundsDonated
        - event: fundsWithdrawn(indexed address,uint256,uint256)
          handler: handleFundsWithdrawn
        - event: milestoneCreated(indexed address,uint256,uint256,string)
          handler: handleMilestoneCreated
        - event: milestoneRejected(uint256,uint256)
          handler: handleMilestoneRejected
```

### Notable Portions of the `subgraph.yaml` File

* The ` ipfsOnEthereumContracts` of the features key allows the subgraph to pull data from IPFS. If your subgraph makes use of data stored on IPFS, you should include the features with a value of ` ipfsOnEthereumContracts`

* `dataSources` : 
   * kind : ethereum/contract
   * network: goerli (blockchain network where the contract is deployed)
   * source:
        * address: "0xeB1F85B8bc1694Dc74789A744078D358cb88117f" ( address contract   
           was deployed
        * abi: CrowdSourcingFactory ( the abi of the contract)
        *   startBlock: 7763910 ( the block to start indexing from. This is usually from the block the contract was deployed
   * mapping:
         * entities:
               *  CampaignCreator
               *  Campaign
               *  Milestone
               *   Donors
         * eventHandlers:
              * event: newCrowdFundingCreated(indexed address,uint256,address,string)
              * handler: handlenewCrowdFundingCreated

The contract factory creates new contracts using clones. The `newCrowdFundingCreated` event is emitted when a new `CrowdFundingContract` is created. We have defined a handler called `handlenewCrowdFundingCreated` that gets fired anytime the contract emits an event. The `newCrowdFundingCreated` event takes four parameters as input.

> Note: Remove all spaces when writing your event. <br/> 
Write like so <br/>
`newCrowdFundingCreated(indexed address,uint256,address,string)` <br/>
don't include spaces within your parameters like so below: <br/>
`newCrowdFundingCreated(indexed address, uint256, address, string)` <br/>
The compiler will run into errors when compiling the subgraph.

* templates

Only at the point of creation can the contract address of a contract created from a factory contract be known. As a result, we cannot use `datasources` in the `subgraph.yaml` file for the `CrowdFundingContract`. We use `templates` to define the `entities`, `events`, and `eventHandlers`. The `templates` fields are similar to the `datasources`. Most of the events we are interested in are in the `templates` portion of the `subgraph.yaml` file.

```
 eventHandlers:
     - event: fundsDonated(indexed address,uint256,uint256)
     handler: handleFundsDonated
     - event: fundsWithdrawn(indexed address,uint256,uint256)
     handler: handleFundsWithdrawn
     - event: milestoneCreated(indexed address,uint256,uint256,string)
     handler: handleMilestoneCreated
     - event: milestoneRejected(uint256,uint256)
     handler: handleMilestoneRejected
```

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

## The Mappings File

We use AssemblyScript to write the handlers for event processing. AssemblyScript is a more stringent version of Typescript. When an event is fired or emitted by the indexed smart contract, the handlers handle the logic determining how data should be retrieved and stored. The data is translated and stored following the defined schema.

### `handlenewCrowdFundingCreated`

```
export function handlenewCrowdFundingCreated(event: newCrowdFundingCreated):void{
  let newCampaign = Campaign.load(event.params.cloneAddress.toHexString());
  let campaignCreator = CampaignCreator.load(event.params.owner.toHexString());
  if ( newCampaign === null ){
    newCampaign = new Campaign(event.params.cloneAddress.toHexString());
    let metadata = ipfs.cat(event.params.fundingCID + "/data.json");
    newCampaign.campaignCID = event.params.fundingCID;
    if ( metadata ){
      const value = json.fromBytes(metadata).toObject();
      const details = value.get("details");

      if ( details ){
        newCampaign.details = details.toString();
      }
    }
    newCampaign.owner = event.params.owner.toHexString();
    newCampaign.dateCreated = event.block.timestamp;
    newCampaign.amountSought = event.params.amount;
    newCampaign.campaignRunning = true;
  }
  if (campaignCreator === null){
    campaignCreator = new CampaignCreator(event.params.owner.toHexString());
    campaignCreator.fundingGiven = integer.ZERO;
    campaignCreator.fundingWithdrawn = integer.ZERO; 
}
  CrowdFundingContract.create(event.params.cloneAddress);
  newCampaign.save();
  campaignCreator.save();
}

```

This mapping function receives an event called `newCrowdFundingCreated` as a parameter. The `newCrowdFundingCreated` event has the following parameters in the contract:

```
 event newCrowdFundingCreated(
        address indexed owner,
        uint256 amount,
        address cloneAddress,
        string fundingCID
    );
```
The `newCrowdFundingCreated` event is fired when a new `CrowdFundingContract` is created. Inside the function, we first try to load a `Campaign` from the graph datastore using the address of a newly created `CrowdFundingContract`, which we access from the `event.params` object of the emitted event. `toHexString()` is appended to convert it to a string.

```
  let newCampaign = Campaign.load(event.params.cloneAddress.toHexString());
```

Next, we also do the same for the `CampaignCreator`.

```
  let campaignCreator = CampaignCreator.load(event.params.owner.toHexString());
```
> Note: The `Campaign` and `CampaignCreator` are from the defined schema. Don't forget to 
`npm run codegen` on the terminal after making any change to the schema. 

The `CampaignCreator` is the owner of the fundraising campaign. 

If the value of `newCampaign` is null, which means a contract with that address has not been created before, we then create a new Campaign using the contract address of the deployed `CrowdFundingContract`.

```
 newCampaign = new Campaign(event.params.cloneAddress.toHexString());
```
We then retrieve the campaign metadata on IPFS. Remember that we are saving the IPFS hash in the event parameters as the `fundingCID`.

```
 import { ipfs, json } from "@graphprotocol/graph-ts";
 let metadata = ipfs.cat(event.params.fundingCID + "/data.json");
```

In our subgraph manifest, we added `ipfsOnEthereumContracts` so that we will be able to query data on IPFS. 

```
  if ( metadata ){
      const value = json.fromBytes(metadata).toObject();
      const details = value.get("details");

      if ( details ){
        newCampaign.details = details.toString();
      }
    }
```
We deconstruct the data inside if the `metadata` is retrieved from IPFS. We retrieve the `details` key of the object and save it as a string to `newCampaign.details`.

> Note: The json file uploaded to IPFS is called `data.json`, and inside the JSON object, we have a key of `details` inside the file. 

We also save other fields in the `Campaign` entities:

```
  newCampaign.owner = event.params.owner.toHexString();
  newCampaign.dateCreated = event.block.timestamp;
  newCampaign.amountSought = event.params.amount;
  newCampaign.campaignRunning = true;
 ```
The `amountSought` is got from `event.params.amount`, `dateCreated` is from the `event.block.timestamp` (current time of the block) and `campaignRunning` is set to `true`.


If the campaign owner record is not already saved, we create a new one like so.

```
  if (campaignCreator === null){
    campaignCreator = new CampaignCreator(event.params.owner.toHexString());
    campaignCreator.fundingGiven = integer.ZERO;
    campaignCreator.fundingWithdrawn = integer.ZERO; 
}
```
`fundingGiven` and `fundingWithdrawn` is set to 0.

The code below creates the template used for this particular `CrowdFundingContract` instance. 


 ```
    CrowdFundingContract.create(event.params.cloneAddress);
 ```

Finally, we save the `newCampaign` and `campaignCreator` instances. 

```
  newCampaign.save();
  campaignCreator.save();
```
We call the above sequence for every new `CrowdfundingContract` created by the factory contract.

Key take away from this handler is:

* Check if data is saved for a `Campaign` and `CampaignCreator` by loading from the data store using the `cloneAddress` and `owner` address from the `event.params` object.

* Get metadata from IPFS and save it to the `Campaign`. 
* Create a new template for the contract instance.
* save all data back to the store by calling the `save` method of the created instances of `Campaign` and `CampaignCreator`.


### The `handleFundsDonated` Event

The contract emits this event when an address donates funds to a campaign. The function receives as an input a `fundsDonated` event which has the following structure:

```
event fundsDonated(address indexed donor, uint256 amount, uint256 date);
```

```
export function handleFundsDonated(event: fundsDonated ):void {
  //get the campaign we are donating to
  const campaign = Campaign.load(event.transaction.to!.toHexString());
    if ( campaign ){
      //we save the donation in the Donor entity
      const newDonor = new Donors(event.transaction.hash.toHexString().concat("-").concat(event.transaction.from.toHexString()))
      newDonor.amount = event.params.amount;
      newDonor.campaign = campaign.id;
      newDonor.donorAddress = event.params.donor;
      newDonor.date = event.params.date;
      newDonor.save();
  
      //get the campaignCreator and add the donation to the campainCreator
      const campaignCreator = CampaignCreator.load(campaign.owner);
      if ( campaignCreator && campaignCreator.fundingGiven ){
        campaignCreator.fundingGiven = campaignCreator.fundingGiven!.plus(event.params.amount);
        campaignCreator.save();
      }
    }
}
```

This code below gets the campaign we are donating to:
```
const campaign = Campaign.load(event.transaction.to!.toHexString());
```
Remember that we saved a new `Campaign` entity using its deployed address. We can load a saved campaign using the `to` field of the `event.transaction`. The `!` mark after `to` tells the compiler that, hey, the `to` field will not be nullable. 

After retrieving the `Campaign` we are donating to, we need to save a new `Donors` entity using a combination of the `event.transaction.hash.toHexString()` and  
`event.transaction.from.toHexString()` to form a unique `id`

```
  const newDonor = new Donors(event.transaction.hash.toHexString().concat("-").concat(event.transaction.from.toHexString()))
```
The donor's field parameter is saved, and we retrieve the ``CampaignCreator` saved entity using the `owner` field value of the `Campaign` entity.

```
 const campaignCreator = CampaignCreator.load(campaign.owner);
```

We increment the `fundingGiven` field of the `campaignCreator` with the amount donated by the donor. 


### `handleMilestoneCreated`

This function handles the creation of a new milestone. Contract creators must create milestones that donors approve of the campaign before they can withdraw donated funds. The `milestoneCreated` event has the following signature:

```
 event milestoneCreated(address indexed owner,uint256 datecreated,uint256 period,
  string milestoneCID
 );
```

```
 export function handleMilestoneCreated(event: milestoneCreated):void {
  const newMilestone = new Milestone(event.transaction.hash.toHexString().concat("-").concat(event.transaction.from.toHexString()))
    const campaign = Campaign.load(event.transaction.to!.toHexString());
    if ( campaign ){
      newMilestone.campaign = campaign.id;
      newMilestone.milestonestatus = "Pending";
      newMilestone.milestoneCID = event.params.milestoneCID;
      let metadata = ipfs.cat(event.params.milestoneCID + "/data.json");
      if ( metadata ){
        const value = json.fromBytes(metadata).toObject();
        const details = value.get("details");
  
        if ( details ){
          newMilestone.details = details.toString();
        }
      }
      newMilestone.periodToVote = event.params.period;
      newMilestone.dateCreated = event.params.datecreated;
     
      newMilestone.save();
       //update the campaign with the current milestone
       campaign.currentMilestone = newMilestone.id;
       campaign.save()
    }
}
```

The function creates a new `Milestone` entity using a combination of the transaction hash and the address of the transaction sender. We load the `Campaign` entity that the milestone is for using the contract address in the transaction. We retrieve the contract address from `event.transaction.to`.

We load milestone details data from IPFS and fill all fields of the newly created milestone. We then update the `currentMilestone` of the campaign with the value of the newly created milestone.

### The `handleFundsWithdrawn` Function

This function handles the event when a campaign owner withdraws funds from the contract. It takes as an input an event titled `fundsWithdrawn`, which has the following signature:

```
  event fundsWithdrawn(address indexed owner, uint256 amount, uint256 date);
```

```
export function handleFundsWithdrawn(event: fundsWithdrawn):void {
   let campaignCreator = CampaignCreator.load(event.params.owner.toHexString());
   if ( campaignCreator && campaignCreator.fundingWithdrawn){
     //increment the amount already withdrawan
     const totalWithdrawal = campaignCreator.fundingWithdrawn!.plus((event.params.amount))
     campaignCreator.fundingWithdrawn = totalWithdrawal;
     campaignCreator.save();
   }

   //set the current milestone to Approved
   //load the milestone and set it to Approved
    let campaign = Campaign.load((event.transaction.to!.toHexString()))
   
   if ( campaign && campaign.currentMilestone ){
      const currentMilestoneId = campaign.currentMilestone;
      //load the milestone
      const milestone = Milestone.load(currentMilestoneId!);
      if ( milestone && milestone.milestonestatus === "Pending" ){
        //check if the milestonestatus is pending
        //update it to Approved
        milestone.milestonestatus = "Approved";
        milestone.save();
      }
     }
}
```
The function loads the campaign creator data from the datastore using the `owner` field of the `event.params` object. It increments the `totalWithdrawal` field of the `campaignCreator` and saves it. Next, it loads the `Campaign`, that the owner is withdrawing funds from using `event.transaction.to`.

```
   let campaign = Campaign.load((event.transaction.to!.toHexString()))
```
It loads a `Milestone` entity using the `campaign.currentMilestone` as an `id`.

```
  const milestone = Milestone.load(currentMilestoneId!);
```
The loaded `milestonestatus` is set to `"Approved"` if it is pending. 

> Note: A contract owner can only make three withdrawals from the crowdfunding contract balance. For this to happen, they have to create milestones.

```
 milestone.milestonestatus = "Approved";
```

### `handleMilestoneRejected`

This handler is fired when a created milestone fails. 

```
export function handleMilestoneRejected(event: milestoneRejected):void{
    const campaign = Campaign.load(event.transaction.to!.toHexString())
    if ( campaign && campaign.currentMilestone){
     const currentMilestoneId = campaign.currentMilestone
       //load the milestone
       const milestone = Milestone.load(currentMilestoneId!);
       if ( milestone && milestone.milestonestatus === "Pending" ){
         //check if the milestonestatus is pending
         //update it to Approved
         milestone.milestonestatus = "Rejected";
         milestone.save();
       }
     
    }
}
```
It sets the status of the current milestone of a campaign to `"Rejected"`. 


## Compiling and Deploying the Subgraph

Currently, our subgraph is fully defined and ready for deployment to the hosted service.

Select the "Show commands" button under Deploy in the subgraph you created on The Graph's Hosted Service.

Run the command below to authenticate you as the subgraph owner to the hosted service:

```
graph auth --product hosted-service <ACCESS_TOKEN>
```

> Note: replace `<ACCESS_TOKEN>` with your access token. You find it on the subgraph page.

Next, run the command to deploy your subgraph to the hosted service.

```
  graph deploy --product hosted-service <GITHUB_USER>/<SUBGRAPH NAME>
```
> Replace <GITHUB_USER> with your GitHub username and <SUBGRAPH NAME> with the name of the subgraph.

After deploying, your subgraph will get indexed, and you can query the subgraph for data after it has finished indexing.


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

## Conclusion

In this series, we have created a subgraph from the smart contract deployed in the first [series](https://blog.developerdao.com/creating-a-decentralised-crowd-funding-contract-with-solidity). Next, we will create a frontend to consume data in the final part of this tutorial exercise. 

You can find the code for this post on [Github](https://github.com/jamiebones/crowdfunding-subgraph).
The subgraph for the tutorial is [here](https://thegraph.com/hosted-service/subgraph/jamiebones/funding)
