Skip to main content

Loading Linked Entities

Introduction

TLDR: When you have a schema that has entities that link/reference other entities (linked entities), you can use the loaders argument to load those linked entities from your handler.

Sometimes the entities that you want loaded in your handler are nested one or more layers deep on the entity that you have the ID for in the loader.

Another prominant use case for linked entities: You may have a global entity (an entity that has a hardcoded ID) that references other entities. Without linked entity loaders, you wouldn't be able to load and access those referenced entities, so these types of loaders are extremely important for many types of advanced indexers.

Example

The below schema shows 4 user-defined entities that reference/link to each other. What if the event only contains the ID of entity A, but we care about the important information entity ImportantEntityICareAbout that is linked via A->B->C->ImportantEntityICareAbout?

schema.graphql

type A {
id: ID!
b: B!
c: [C!]! @derivedFrom(field: "a")
optionalBigInt: BigInt
}
type B {
id: ID!
c: C!
}
type C {
id: ID!
a: A!
importantData: ImportantEntityICareAbout!
}
type ImportantEntityICareAbout {
id: ID!
otherData: String!
}

config.yaml

For illustration there is a TestEvent:

networks:
- id: 123456
contracts:
- name: Gravatar
events:
- event: "TestEvent"

Event Handler file

GravatarContract.TestEvent.loader(({ event, context }) => {
context.A.load(event.params.id, {
loadB: { loadC: { loadImportantData: true }, loadA: {} },
});
// ... other loaders
});

GravatarContract.TestEvent.handler(({ event, context }) => {
const entityA = context.A.get(event.params.id);
const linkedB = context.A.getB(entityA);
const linkedC = context.B.getC(linkedB);
const importantDataEntity = context.C.getImportantData(linkedC);
// ... rest of the handler that uses or updates these entities.
});

If the entity you want to load has linked entities of its own, then you need to put a {} (empty object next to the name to indicate stopping the recursive loading at that point), otherwise you must put a true. Thus in the above example, we put true next to the loadImportantData, and a {} next to the inner loadA.

Note: Currently loading data from derived fields is unsupported.