Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Creating a Subgraph #786

Merged
merged 5 commits into from
Oct 7, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 24 additions & 18 deletions website/pages/en/developing/creating-a-subgraph.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ In this configuration:
- `topic2` is configured to filter `Transfer` events where `0xAddressB` and `0xAddressC` is the receiver.
- The subgraph will index transactions that occur in either direction between multiple addresses allowing for comprehensive monitoring of interactions involving all addresses.

## Declared eth_call
### Declared eth_call

> **Requires**: [SpecVersion](#specversion-releases) >= `1.2.0`. Currently, `eth_calls` can only be declared for event handlers.

Expand All @@ -326,13 +326,13 @@ This feature does the following:
- Allows faster data fetching, resulting in quicker query responses and a better user experience.
- Reduces wait times for applications that need to aggregate data from multiple Ethereum calls, making the data retrieval process more efficient.

### Key Concepts
#### Key Concepts

- Declarative `eth_calls`: Ethereum calls that are defined to be executed in parallel rather than sequentially.
- Parallel Execution: Instead of waiting for one call to finish before starting the next, multiple calls can be initiated simultaneously.
- Time Efficiency: The total time taken for all the calls changes from the sum of the individual call times (sequential) to the time taken by the longest call (parallel).

### Scenario without Declarative `eth_calls`
#### Scenario without Declarative `eth_calls`

Imagine you have a subgraph that needs to make three Ethereum calls to fetch data about a user's transactions, balance, and token holdings.

Expand All @@ -344,7 +344,7 @@ Traditionally, these calls might be made sequentially:

Total time taken = 3 + 2 + 4 = 9 seconds

### Scenario with Declarative `eth_calls`
#### Scenario with Declarative `eth_calls`

With this feature, you can declare these calls to be executed in parallel:

Expand All @@ -356,13 +356,13 @@ Since these calls are executed in parallel, the total time taken is equal to the

Total time taken = max (3, 2, 4) = 4 seconds

### How it Works
#### How it Works

1. Declarative Definition: In the subgraph manifest, you declare the Ethereum calls in a way that indicates they can be executed in parallel.
2. Parallel Execution Engine: The Graph Node's execution engine recognizes these declarations and runs the calls simultaneously.
3. Result Aggregation: Once all calls are complete, the results are aggregated and used by the subgraph for further processing.

### Example Configuration in Subgraph Manifest
#### Example Configuration in Subgraph Manifest

Declared `eth_calls` can access the `event.address` of the underlying event as well as all the `event.params`.

Expand Down Expand Up @@ -410,22 +410,28 @@ calls:
The ABI file(s) must match your contract(s). There are a few ways to obtain ABI files:

- If you are building your own project, you will likely have access to your most current ABIs.
- If you are building a subgraph for a public project, you can download that project to your computer and get the ABI by using [`truffle compile`](https://truffleframework.com/docs/truffle/overview) or using solc to compile.
- If you are building a subgraph for a public project, you can download that project to your computer and get the ABI by using [`npx hardhat compile`](https://hardhat.org/hardhat-runner/docs/guides/compile-contracts#compiling-your-contracts) or using solc to compile.
idalithb marked this conversation as resolved.
Show resolved Hide resolved
- You can also find the ABI on [Etherscan](https://etherscan.io/), but this isn't always reliable, as the ABI that is uploaded there may be out of date. Make sure you have the right ABI, otherwise running your subgraph will fail.

## The GraphQL Schema
### The GraphQL Schema

The schema for your subgraph is in the file `schema.graphql`. GraphQL schemas are defined using the GraphQL interface definition language. If you've never written a GraphQL schema, it is recommended that you check out this primer on the GraphQL type system. Reference documentation for GraphQL schemas can be found in the [GraphQL API](/querying/graphql-api) section.
The schema for your subgraph is in the file `schema.graphql`. GraphQL schemas are defined using the GraphQL interface definition language. If you've never written a GraphQL schema, it is recommended that you check out this primer on the GraphQL type system. Reference documentation for GraphQL schemas can be found in the [GraphQL API](/querying/graphql-api/) section.

## Defining Entities
### Defining Entities

Before defining entities, it is important to take a step back and think about how your data is structured and linked. All queries will be made against the data model defined in the subgraph schema and the entities indexed by the subgraph. Because of this, it is good to define the subgraph schema in a way that matches the needs of your dapp. It may be useful to imagine entities as "objects containing data", rather than as events or functions.
Before defining entities, it is important to take a step back and think about how your data is structured and linked.

With The Graph, you simply define entity types in `schema.graphql`, and Graph Node will generate top level fields for querying single instances and collections of that entity type. Each type that should be an entity is required to be annotated with an `@entity` directive. By default, entities are mutable, meaning that mappings can load existing entities, modify them and store a new version of that entity. Mutability comes at a price, and for entity types for which it is known that they will never be modified, for example, because they simply contain data extracted verbatim from the chain, it is recommended to mark them as immutable with `@entity(immutable: true)`. Mappings can make changes to immutable entities as long as those changes happen in the same block in which the entity was created. Immutable entities are much faster to write and to query, and should therefore be used whenever possible.
- All queries will be made against the data model defined in the subgraph schema and the entities indexed by the subgraph. As a result, it is good to define the subgraph schema in a way that matches the needs of your dapp.
- It may be useful to imagine entities as "objects containing data", rather than as events or functions.
- You define entity types in `schema.graphql`, and Graph Node will generate top level fields for querying single instances and collections of that entity type.
idalithb marked this conversation as resolved.
Show resolved Hide resolved
- Each type that should be an entity is required to be annotated with an `@entity` directive.
- By default, entities are mutable, meaning that mappings can load existing entities, modify them and store a new version of that entity.
- Mutability comes at a price, so for entity types that will never be modified, such as those containing data extracted verbatim from the chain, it is recommended to mark them as immutable with `@entity(immutable: true)`.
- If changes happen in the same block in which the intity was created, then mappings can make changes to immutable entities. Immutable entities are much faster to write and to query so they should be used whenever possible.
idalithb marked this conversation as resolved.
Show resolved Hide resolved

### Good Example
#### Good Example

The `Gravatar` entity below is structured around a Gravatar object and is a good example of how an entity could be defined.
The following `Gravatar` entity is structured around a Gravatar object and is a good example of how an entity could be defined.

```graphql
type Gravatar @entity(immutable: true) {
Expand All @@ -437,9 +443,9 @@ type Gravatar @entity(immutable: true) {
}
```

### Bad Example
#### Bad Example

The example `GravatarAccepted` and `GravatarDeclined` entities below are based around events. It is not recommended to map events or function calls to entities 1:1.
The following example of `GravatarAccepted` and `GravatarDeclined` entities is based around events. It is not recommended to map events or function calls to entities 1:1.
idalithb marked this conversation as resolved.
Show resolved Hide resolved

```graphql
type GravatarAccepted @entity {
Expand All @@ -457,7 +463,7 @@ type GravatarDeclined @entity {
}
```

### Optional and Required Fields
#### Optional and Required Fields

Entity fields can be defined as required or optional. Required fields are indicated by the `!` in the schema. If a required field is not set in the mapping, you will receive this error when querying the field:

Expand All @@ -473,7 +479,7 @@ For some entity types the `id` is constructed from the id's of two other entitie

#### GraphQL Supported Scalars

We support the following scalars in our GraphQL API:
The following scalars are supported in the GraphQL API:

| Type | Description |
| --- | --- |
Expand Down
Loading