Video walkthrough
Getting the ABI
If the contract you’re interested in indexing is a contract you deployed, then you’ll have the contract address and ABI handy. Otherwise, you can use a mix of public explorer tools to find this information. For example, if we’re interested in indexing the friend.tech contract…
Contract ABI
section.Save the ABI to your local file system and make a note of the contract address. Also make a note of the block number the contract was deployed at, you’ll need this at a later step.
Creating the configuration file
The next step is to create the Instant Subgraph configuration file (e.g. friendtech-config.json
). This file consists of five key sections:
As of October 2023, our Instant Subgraph configuration system is on version 1. This may change in the future. This is not the version number of your subgraph, but of Goldsky’s configuration file format.
This is a name of your choice that helps you understand what this config is for. It is only used for internal debugging. For this guide, we’ll use friendtech
.
These three sections are interconnected.
ftshares
and abi.json
.The abi name in instances
should match a key in abis
, in this example, ftshares
. It is possible to have more than one chains
and more than one ABI. Multiple chains will result in multiple subgraphs. The file abi.json
in this example should contain the friendtech ABI downloaded from here.
This configuration can handle multiple contracts with distinct ABIs, the same contract across multiple chains, or multiple contracts with distinct ABIs on multiple chains.
For a complete reference of the various properties, please see the Instant Subgraphs references docs
Deploying the subgraph
With your configuration file ready, it’s time to deploy the subgraph.
goldsky login
.goldsky subgraph deploy name/version --from-abi <path-to-config-file>
, then pass in the path to the config file you created. Note - do NOT pass in the ABI itself, but rather the config file defined above. Example: goldsky subgraph deploy friendtech/1.0 --from-abi friendtech-config.json
Goldsky will generate all the necessary subgraph code, deploy it, and return an endpoint that you can start querying.
Clicking the endpoint link takes you to a web client where you can browse the schema and draft queries to integrate into your app.
Enrichments are a powerful way to add additional data to your subgraph by performing eth calls in the middle of an event or call handler.
See the enrichments configuration reference for more information on how to define these enrichments, and for an example configuration with enrichments.
@graphprotocol/graph-ts
beyond BigInt
, Bytes
, and store
can be declared in the options.imports
field of the enrichment (e.g., BigDecimal
).required
or having another call declare them as a depends_on
dependency will abort if the call is not successful, otherwise the call output value will remain as null
.declared
will configure the subgraph to execute the call prior to invoking the mapping handler. This can be useful for performance reasons, but only works for eth calls that have no mapping handler dependencies.pre
and post
expressions for conditions
to test before and after the call, if either fails the call is aborted. Since these are expressions, they can be dynamic or constant values.source
is an expression and therefore allows for dynamic values using math or concatenations. If the source
is simply a contract address then it will be automatically converted to an Address
type.params
is an expression list and can also be dynamic values or constants.id
expression to be defined for each entity, id
can by a dynamic value or a constant. this id
is appended to the parent entity id
to create a unique id
for each enrichment entity in the list.explicit_id
flag to true
, this will use the value of id
without appending it to the parent entity id
, creating an addressable entity that can be updated.Below are some various examples of configurations for different scenarios. To keep each example brief, we will only show the enrich
section of the configuration, and in most cases only the part of the enrich
section that is relevant. See the enrichments configuration reference for the full configuration reference.
Here we are enabling debugging for the enrichment (this will output the enrichment steps to the subgraph log), as well as importing BigDecimal
for use in a calls
or entities
section.
Here we are calling a function on the same contract as the trigger event. This means we can omit the abi
and source
configuration fields, as they are implied in this scenario, we only need to include the name
and params
fields (if the function declares paramters). We can refer to the result of this call using calls.balance
.
Here we are creating a 2-call dependency, where the second call depends on the first call (the params are calls.owner
meaning we need the value of the owner
call before we can invoke balanceOf
). This means that if the first call fails, the second call will not be executed. Calls are always executed in the order they are configured, so the second call will have access to the output of the first call (in this example, we use that output as a parameter to the second call). We can list multiple calls in the depends_on
array to create a dependency graph (if needed). Adding a call to the depends_on
array will not automatically re-order the calls, so be sure to list them in the correct order.
Here we are calling a function on an external contract, where we know the address of the contract ahead of time. In this case, we need to include the abi
and source
configuration fields.
Here we are setting up a 2 call chain to first determine the contract address, then call a function on that contract. In our example, the contractAddress
function is returning an Address
type so we can use the call result directly in the source
field of the second call. If contractAddress
was instead returning a string
type, then we would use "source": "Address.fromString(calls.contract_address)"
, though this would be an unusual case to observe.
Here we are marking a call as required, meaning that if the call fails then the enrichment as a whole will be aborted. This is useful when you do not want to create a new entity (or enrich an existing entity) if the call does not return any meaningful data. Also note that when using depends_on
, the dependency call is automatically marked as required. This should be used when the address of the contract being called may not always implement the function being called.
Here we are using conditions to prevent a call from being executed or to abort the enrichment if the call result is not satisfactory. Avoiding an eth call can have a big performance impact if the inputs to the call are often invalid. Avoiding the creation of an entity can save on entity counts if the entity is not needed or useful for various call results. Conditions are simply checked at their target site in the enrichment, and evaluated to its negation to check if an abort is necessary (e.g., true
becomes !(true)
, which is always false and therefore never aborts). In this example, we’re excluding the call if the owner
is in a deny list, and we’re aborting the enrichment if the balance is 0
.
Here were are simply replicating the id
field from the event params into our enrichment entity. This can be useful if you want to filter or sort the enrichment entities by this field.
Here we are applying a serialization function to the value of a call result. This is necessary as the enrichment code generator does not resolve the effective type of an expression, so if there is a type mismatch a serialization function must be applied (in this case String
vs Address
).
Here we are conditionally setting the value of usd_balance
on whether or not the usdc_balance
call was successful. If the call was not successful, then we set the value to BigDecimal.zero()
, otherwise we divide the call result by 10^6
(USDC decimals) to convert the balance to a USD
value.
Can't find what you're looking for? Reach out to us at support@goldsky.com for help.
Here we are creating multiple instances of an entity in a single enrichment. Each entity id will be suffixed with the provided id
value.
Here we are creating an entity that is addressable by an explicit id. This means that we can update this entity with new values.
We must use an array for our entity definition to allow setting the explicit_id
flag.
Here are some examples of various instant subgraph configurations. Each example builds on the previous example.
Each of these examples can be saved locally to a file (e.g., subgraph.json
) and deployed using goldsky subgraph deploy nouns/1.0.0 --from-abi subgraph.json
.
This is a basic instant subgraph configuration, a great starting point for learning about instant subgraphs.
This example describes a very simple enrichment that adds a balance
field to a Balance
enrichment entity. This balance
field is populated by calling the balanceOf
function on the to
address of the Transfer
event.
This example alters our previous example by capturing the balance
field on both FromBalance
and ToBalance
enrichment entities. This balance
field is populated by calling the balanceOf
function on both the from
and to
address of the Transfer
event.
This example alters our previous example balance entities to become a single mutable Balance
entity, so that both sender and receiver use the same entity.
We can now query the Balance
entity by the owner address (id
) to see the current balance.
This example alters our previous example by adding the declared
flag to boost performance of the balanceOf
eth calls. declared calls only work for eth calls that have no mapping handler dependencies, in other words the call can be executed from the event params only. Also note that call handlers do not support delcared calls (yet), if declared
is set on a call handler enrichment it will be ignored.
Video walkthrough
Getting the ABI
If the contract you’re interested in indexing is a contract you deployed, then you’ll have the contract address and ABI handy. Otherwise, you can use a mix of public explorer tools to find this information. For example, if we’re interested in indexing the friend.tech contract…
Contract ABI
section.Save the ABI to your local file system and make a note of the contract address. Also make a note of the block number the contract was deployed at, you’ll need this at a later step.
Creating the configuration file
The next step is to create the Instant Subgraph configuration file (e.g. friendtech-config.json
). This file consists of five key sections:
As of October 2023, our Instant Subgraph configuration system is on version 1. This may change in the future. This is not the version number of your subgraph, but of Goldsky’s configuration file format.
This is a name of your choice that helps you understand what this config is for. It is only used for internal debugging. For this guide, we’ll use friendtech
.
These three sections are interconnected.
ftshares
and abi.json
.The abi name in instances
should match a key in abis
, in this example, ftshares
. It is possible to have more than one chains
and more than one ABI. Multiple chains will result in multiple subgraphs. The file abi.json
in this example should contain the friendtech ABI downloaded from here.
This configuration can handle multiple contracts with distinct ABIs, the same contract across multiple chains, or multiple contracts with distinct ABIs on multiple chains.
For a complete reference of the various properties, please see the Instant Subgraphs references docs
Deploying the subgraph
With your configuration file ready, it’s time to deploy the subgraph.
goldsky login
.goldsky subgraph deploy name/version --from-abi <path-to-config-file>
, then pass in the path to the config file you created. Note - do NOT pass in the ABI itself, but rather the config file defined above. Example: goldsky subgraph deploy friendtech/1.0 --from-abi friendtech-config.json
Goldsky will generate all the necessary subgraph code, deploy it, and return an endpoint that you can start querying.
Clicking the endpoint link takes you to a web client where you can browse the schema and draft queries to integrate into your app.
Enrichments are a powerful way to add additional data to your subgraph by performing eth calls in the middle of an event or call handler.
See the enrichments configuration reference for more information on how to define these enrichments, and for an example configuration with enrichments.
@graphprotocol/graph-ts
beyond BigInt
, Bytes
, and store
can be declared in the options.imports
field of the enrichment (e.g., BigDecimal
).required
or having another call declare them as a depends_on
dependency will abort if the call is not successful, otherwise the call output value will remain as null
.declared
will configure the subgraph to execute the call prior to invoking the mapping handler. This can be useful for performance reasons, but only works for eth calls that have no mapping handler dependencies.pre
and post
expressions for conditions
to test before and after the call, if either fails the call is aborted. Since these are expressions, they can be dynamic or constant values.source
is an expression and therefore allows for dynamic values using math or concatenations. If the source
is simply a contract address then it will be automatically converted to an Address
type.params
is an expression list and can also be dynamic values or constants.id
expression to be defined for each entity, id
can by a dynamic value or a constant. this id
is appended to the parent entity id
to create a unique id
for each enrichment entity in the list.explicit_id
flag to true
, this will use the value of id
without appending it to the parent entity id
, creating an addressable entity that can be updated.Below are some various examples of configurations for different scenarios. To keep each example brief, we will only show the enrich
section of the configuration, and in most cases only the part of the enrich
section that is relevant. See the enrichments configuration reference for the full configuration reference.
Here we are enabling debugging for the enrichment (this will output the enrichment steps to the subgraph log), as well as importing BigDecimal
for use in a calls
or entities
section.
Here we are calling a function on the same contract as the trigger event. This means we can omit the abi
and source
configuration fields, as they are implied in this scenario, we only need to include the name
and params
fields (if the function declares paramters). We can refer to the result of this call using calls.balance
.
Here we are creating a 2-call dependency, where the second call depends on the first call (the params are calls.owner
meaning we need the value of the owner
call before we can invoke balanceOf
). This means that if the first call fails, the second call will not be executed. Calls are always executed in the order they are configured, so the second call will have access to the output of the first call (in this example, we use that output as a parameter to the second call). We can list multiple calls in the depends_on
array to create a dependency graph (if needed). Adding a call to the depends_on
array will not automatically re-order the calls, so be sure to list them in the correct order.
Here we are calling a function on an external contract, where we know the address of the contract ahead of time. In this case, we need to include the abi
and source
configuration fields.
Here we are setting up a 2 call chain to first determine the contract address, then call a function on that contract. In our example, the contractAddress
function is returning an Address
type so we can use the call result directly in the source
field of the second call. If contractAddress
was instead returning a string
type, then we would use "source": "Address.fromString(calls.contract_address)"
, though this would be an unusual case to observe.
Here we are marking a call as required, meaning that if the call fails then the enrichment as a whole will be aborted. This is useful when you do not want to create a new entity (or enrich an existing entity) if the call does not return any meaningful data. Also note that when using depends_on
, the dependency call is automatically marked as required. This should be used when the address of the contract being called may not always implement the function being called.
Here we are using conditions to prevent a call from being executed or to abort the enrichment if the call result is not satisfactory. Avoiding an eth call can have a big performance impact if the inputs to the call are often invalid. Avoiding the creation of an entity can save on entity counts if the entity is not needed or useful for various call results. Conditions are simply checked at their target site in the enrichment, and evaluated to its negation to check if an abort is necessary (e.g., true
becomes !(true)
, which is always false and therefore never aborts). In this example, we’re excluding the call if the owner
is in a deny list, and we’re aborting the enrichment if the balance is 0
.
Here were are simply replicating the id
field from the event params into our enrichment entity. This can be useful if you want to filter or sort the enrichment entities by this field.
Here we are applying a serialization function to the value of a call result. This is necessary as the enrichment code generator does not resolve the effective type of an expression, so if there is a type mismatch a serialization function must be applied (in this case String
vs Address
).
Here we are conditionally setting the value of usd_balance
on whether or not the usdc_balance
call was successful. If the call was not successful, then we set the value to BigDecimal.zero()
, otherwise we divide the call result by 10^6
(USDC decimals) to convert the balance to a USD
value.
Can't find what you're looking for? Reach out to us at support@goldsky.com for help.
Here we are creating multiple instances of an entity in a single enrichment. Each entity id will be suffixed with the provided id
value.
Here we are creating an entity that is addressable by an explicit id. This means that we can update this entity with new values.
We must use an array for our entity definition to allow setting the explicit_id
flag.
Here are some examples of various instant subgraph configurations. Each example builds on the previous example.
Each of these examples can be saved locally to a file (e.g., subgraph.json
) and deployed using goldsky subgraph deploy nouns/1.0.0 --from-abi subgraph.json
.
This is a basic instant subgraph configuration, a great starting point for learning about instant subgraphs.
This example describes a very simple enrichment that adds a balance
field to a Balance
enrichment entity. This balance
field is populated by calling the balanceOf
function on the to
address of the Transfer
event.
This example alters our previous example by capturing the balance
field on both FromBalance
and ToBalance
enrichment entities. This balance
field is populated by calling the balanceOf
function on both the from
and to
address of the Transfer
event.
This example alters our previous example balance entities to become a single mutable Balance
entity, so that both sender and receiver use the same entity.
We can now query the Balance
entity by the owner address (id
) to see the current balance.
This example alters our previous example by adding the declared
flag to boost performance of the balanceOf
eth calls. declared calls only work for eth calls that have no mapping handler dependencies, in other words the call can be executed from the event params only. Also note that call handlers do not support delcared calls (yet), if declared
is set on a call handler enrichment it will be ignored.