Multichain Indexing
This page explains how to index from multiple chains in a single indexer.
This means that events from contracts deployed on multiple chains can be used to create and update entities defined in the schema file.
Users are required to populate the network
section in config.yaml
file for each chain and specify a contract to index from.
Users can then specify event loader/handler for each of the contracts specified in config.yaml
file.
Multichain Indexing on Greeter template
Config file
name: Greeter
description: Greeter indexer
networks:
- id: 137 # Polygon
start_block: 45336336
contracts:
- name: PolygonGreeter
abi_file_path: abis/greeter-abi.json
address: "0x9D02A17dE4E68545d3a58D3a20BbBE0399E05c9c"
handler: ./src/EventHandlers.bs.js
events:
- event: "NewGreeting"
requiredEntities:
- name: "Greeting"
- event: "ClearGreeting"
requiredEntities:
- name: "Greeting"
- id: 59144 # Linea
start_block: 367801
contracts:
- name: LineaGreeter
abi_file_path: abis/greeter-abi.json
address: "0xdEe21B97AB77a16B4b236F952e586cf8408CF32A"
handler: ./src/EventHandlers.bs.js
events:
- event: "NewGreeting"
requiredEntities:
- name: "Greeting"
- event: "ClearGreeting"
requiredEntities:
- name: "Greeting"
The Greeter indexer listens to NewGreeting
and ClearGreeting
events from both PolygonGreeter
and LineaGreeter
contracts to update the Greeting
entity.
Schema file
type Greeting {
id: ID!
greetings: [String!]!
latestGreeting: String!
numberOfGreetings: Int!
}
Event Handler file
- Javascript
- Typescript
- Rescript
let {
PolygonGreeterContract,
LineaGreeterContract,
} = require("../generated/src/Handlers.bs.js");
PolygonGreeterContract.NewGreeting.loader((event, context) => {
context.Greeting.load(event.params.user);
...
});
PolygonGreeterContract.NewGreeting.handler((event, context) => {
let existingGreeter = context.Greeting.get(event.params.user);
...
});
PolygonGreeterContract.ClearGreeting.loader((event, context) => {
context.Greeting.load(event.params.user);
...
});
PolygonGreeterContract.ClearGreeting.handler((event, context) => {
let existingGreeter = context.Greeting.get(event.params.user);
...
});
LineaGreeterContract.NewGreeting.loader((event, context) => {
context.Greeting.load(event.params.user);
...
});
LineaGreeterContract.NewGreeting.handler((event, context) => {
let existingGreeter = context.Greeting.get(event.params.user);
...
});
LineaGreeterContract.ClearGreeting.loader((event, context) => {
context.Greeting.load(event.params.user);
...
});
LineaGreeterContract.ClearGreeting.handler((event, context) => {
let existingGreeter = context.Greeting.get(event.params.user);
...
});
import {
PolygonGreeterContract_NewGreeting_loader,
PolygonGreeterContract_NewGreeting_handler,
PolygonGreeterContract_ClearGreeting_loader,
PolygonGreeterContract_ClearGreeting_handler,
LineaGreeterContract_NewGreeting_loader,
LineaGreeterContract_NewGreeting_handler,
LineaGreeterContract_ClearGreeting_loader,
LineaGreeterContract_ClearGreeting_handler,
} from "../generated/src/Handlers.gen";
import { GreetingEntity } from "../generated/src/Types.gen";
PolygonGreeterContract_NewGreeting_loader(({ event, context }) => {
context.Greeting.load(event.params.user.toString());
...
});
PolygonGreeterContract_NewGreeting_handler(({ event, context }) => {
let currentGreeter = context.Greeting.get(event.params.user);
...
});
PolygonGreeterContract_ClearGreeting_loader(({ event, context }) => {
context.Greeting.load(event.params.user.toString());
...
});
PolygonGreeterContract_ClearGreeting_handler(({ event, context }) => {
let currentGreeter = context.Greeting.get(event.params.user);
...
});
LineaGreeterContract_NewGreeting_loader(({ event, context }) => {
context.Greeting.load(event.params.user.toString());
...
});
LineaGreeterContract_NewGreeting_handler(({ event, context }) => {
let currentGreeter = context.Greeting.get(event.params.user);
...
});
LineaGreeterContract_ClearGreeting_loader(({ event, context }) => {
context.Greeting.load(event.params.user.toString());
...
});
LineaGreeterContract_ClearGreeting_handler(({ event, context }) => {
let currentGreeter = context.Greeting.get(event.params.user);
...
});
open Types
Handlers.PolygonGreeterContract.NewGreeting.loader((~event, ~context) => {
context.greeting.load(event.params.user->Ethers.ethAddressToString)
...
})
Handlers.PolygonGreeterContract.NewGreeting.handler((~event, ~context) => {
let currentGreeterOpt = context.greeting.get(event.params.user->Ethers.ethAddressToString)
...
})
Handlers.PolygonGreeterContract.ClearGreeting.loader((~event, ~context) => {
context.greeting.load(event.params.user->Ethers.ethAddressToString)
...
})
Handlers.PolygonGreeterContract.ClearGreeting.handler((~event, ~context) => {
let currentGreeterOpt = context.greeting.get(event.params.user->Ethers.ethAddressToString)
...
})
Handlers.LineaGreeterContract.NewGreeting.loader((~event, ~context) => {
context.greeting.load(event.params.user->Ethers.ethAddressToString)
...
})
Handlers.LineaGreeterContract.NewGreeting.handler((~event, ~context) => {
let currentGreeterOpt = context.greeting.get(event.params.user->Ethers.ethAddressToString)
...
})
Handlers.LineaGreeterContract.ClearGreeting.loader((~event, ~context) => {
context.greeting.load(event.params.user->Ethers.ethAddressToString)
...
})
Handlers.LineaGreeterContract.ClearGreeting.handler((~event, ~context) => {
let currentGreeterOpt = context.greeting.get(event.params.user->Ethers.ethAddressToString)
...
})