Update subgraph watcher demo readme (#480)

* Update subgraph watcher demo readme

* Pass extra block data required in subgraph block handler (#486)

* Use codegen config directory name instead of file path

* Get block data from extra event data

* Add extra event data in processBlockAfterEvents

---------

Co-authored-by: neeraj <neeraj.rtly@gmail.com>

* Update example subgraph mapping code for graph-cli upgrade

* Return 0 value for block size in ipld-eth-client

---------

Co-authored-by: neeraj <neeraj.rtly@gmail.com>
Co-authored-by: Prathamesh Musale <prathamesh.musale0@gmail.com>
This commit is contained in:
Nabarun Gogoi 2023-11-24 11:13:40 +05:30 committed by GitHub
parent 937aed139f
commit 6decf61d4c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 38 additions and 38 deletions

View File

@ -499,10 +499,10 @@ export class Indexer implements IndexerInterface {
} }
{{#if (subgraphPath)}} {{#if (subgraphPath)}}
async processBlockAfterEvents (blockHash: string, blockNumber: number): Promise<void> { async processBlockAfterEvents (blockHash: string, blockNumber: number, extraData: ExtraEventData): Promise<void> {
console.time('time:indexer#processBlockAfterEvents-mapping_code'); console.time('time:indexer#processBlockAfterEvents-mapping_code');
// Call subgraph handler for block. // Call subgraph handler for block.
await this._graphWatcher.handleBlock(blockHash, blockNumber); await this._graphWatcher.handleBlock(blockHash, blockNumber, extraData);
console.timeEnd('time:indexer#processBlockAfterEvents-mapping_code'); console.timeEnd('time:indexer#processBlockAfterEvents-mapping_code');
console.time('time:indexer#processBlockAfterEvents-dump_subgraph_state'); console.time('time:indexer#processBlockAfterEvents-dump_subgraph_state');

View File

@ -69,7 +69,8 @@ export async function buildSubgraph (
network?: string network?: string
} }
): Promise<void> { ): Promise<void> {
const subgraphDirectory = path.resolve(codegenConfigPath, subgraphConfig.directory); const codegenConfigDirName = path.dirname(codegenConfigPath);
const subgraphDirectory = path.resolve(codegenConfigDirName, subgraphConfig.directory);
const codegenWorkingDir = process.cwd(); const codegenWorkingDir = process.cwd();
// Change directory to subgraph repo // Change directory to subgraph repo
shell.cd(subgraphDirectory); shell.cd(subgraphDirectory);
@ -102,7 +103,7 @@ export async function buildSubgraph (
const { code: installCode } = shell.exec(`${packageManager} install --force`); const { code: installCode } = shell.exec(`${packageManager} install --force`);
assert(installCode === 0, 'Installing dependencies exited with error'); assert(installCode === 0, 'Installing dependencies exited with error');
const subgraphConfigPath = path.resolve(codegenConfigPath, subgraphConfig.configFile); const subgraphConfigPath = path.resolve(codegenConfigDirName, subgraphConfig.configFile);
// Run graph-cli codegen // Run graph-cli codegen
const { code: codegenCode } = shell.exec(`${packageManager === 'npm' ? 'npx' : packageManager} graph codegen ${subgraphConfigPath}`); const { code: codegenCode } = shell.exec(`${packageManager === 'npm' ? 'npx' : packageManager} graph codegen ${subgraphConfigPath}`);
@ -112,7 +113,7 @@ export async function buildSubgraph (
let buildCommand = `${packageManager === 'npm' ? 'npx' : packageManager} graph build ${subgraphConfigPath}`; let buildCommand = `${packageManager === 'npm' ? 'npx' : packageManager} graph build ${subgraphConfigPath}`;
if (subgraphConfig.networkFilePath) { if (subgraphConfig.networkFilePath) {
const subgraphNetworkFilePath = path.resolve(codegenConfigPath, subgraphConfig.networkFilePath); const subgraphNetworkFilePath = path.resolve(codegenConfigDirName, subgraphConfig.networkFilePath);
assert(subgraphConfig.network, 'Config subgraph.network should be set if using networkFilePath'); assert(subgraphConfig.network, 'Config subgraph.network should be set if using networkFilePath');
const subgraphNetwork = subgraphConfig.network; const subgraphNetwork = subgraphConfig.network;
buildCommand = `${buildCommand} --network-file ${subgraphNetworkFilePath} --network ${subgraphNetwork}`; buildCommand = `${buildCommand} --network-file ${subgraphNetworkFilePath} --network ${subgraphNetwork}`;

View File

@ -16,10 +16,6 @@
* For this demo, an [example subgraph](../graph-node/test/subgraph/example1) will be used * For this demo, an [example subgraph](../graph-node/test/subgraph/example1) will be used
* In [package.json](../graph-node/test/subgraph/example1/package.json), the graph-ts and graph-cli dependencies are replaced by their respective cerc-io forked dependencies
* This needs to be done for running any subgraph project with watcher-ts
* In watcher-ts [packages/graph-node](../graph-node/), deploy an `Example` contract: * In watcher-ts [packages/graph-node](../graph-node/), deploy an `Example` contract:
```bash ```bash
@ -32,13 +28,7 @@
export EXAMPLE_ADDRESS=<EXAMPLE_ADDRESS> export EXAMPLE_ADDRESS=<EXAMPLE_ADDRESS>
``` ```
* In [packages/graph-node/test/subgraph/example1/subgraph.yaml](../graph-node/test/subgraph/example1/subgraph.yaml), set the source address for `Example1` datasource to the `EXAMPLE_ADDRESS`. Then in [packages/graph-node](../graph-node/) run: * In [packages/graph-node/test/subgraph/example1/subgraph.yaml](../graph-node/test/subgraph/example1/subgraph.yaml), set the source address for `Example1` datasource to the `EXAMPLE_ADDRESS`
```bash
yarn build:example
```
* This will run `yarn && yarn codegen && yarn build` script in the example subgraph directory
* In [packages/codegen](./), create a `config.yaml` file: * In [packages/codegen](./), create a `config.yaml` file:
@ -63,10 +53,16 @@
# Flatten the input contract file(s) [true | false] (default: true). # Flatten the input contract file(s) [true | false] (default: true).
flatten: true flatten: true
# Path to the subgraph build (optional). # Config for subgraph
# Can set empty contracts array when using subgraphPath. subgraph:
# Subgraph WASM files should be compiled using @cerc-io/graph-cli # Path to subgraph repo directory containing package.json
subgraphPath: ../graph-node/test/subgraph/example1/build directory: ../graph-node/test/subgraph/example1
# Package manager that is used in subgraph repo for dependencies
packageManager: yarn
# Path to subgraph manifest/config file
configFile: ../graph-node/test/subgraph/example1/subgraph.yaml
``` ```
* Run codegen to generate watcher: * Run codegen to generate watcher:
@ -116,13 +112,7 @@
yarn && yarn build yarn && yarn build
``` ```
* In `packages/test-watcher`, run fill for the subgraph start block: * Configure the upstream GQL and RPC endpoints
```bash
yarn fill --start-block 10 --end-block 10
```
* Subgraph start block is the lowest `startBlock` in example [subgraph.yaml](../graph-node/test/subgraph/example1/subgraph.yaml)
* Run the job-runner: * Run the job-runner:

View File

@ -238,7 +238,7 @@ export class GraphWatcher {
} }
} }
async handleBlock (blockHash: string, blockNumber: number) { async handleBlock (blockHash: string, blockNumber: number, extraData: ExtraEventData) {
// Clear transactions map on handling new block. // Clear transactions map on handling new block.
this._transactionsMap.clear(); this._transactionsMap.clear();
@ -258,11 +258,10 @@ export class GraphWatcher {
continue; continue;
} }
// TODO: Use extraData full block // Check if block data is already fetched in handleEvent method for the same block.
// // Check if block data is already fetched in handleEvent method for the same block. if (!this._context.block || this._context.block.blockHash !== blockHash) {
// if (!this._context.block || this._context.block.blockHash !== blockHash) { this._context.block = await getFullBlock(extraData.ethFullBlock);
// this._context.block = await getFullBlock(this._ethClient, this._ethProvider, blockHash, blockNumber); }
// }
const blockData = this._context.block; const blockData = this._context.block;
assert(blockData); assert(blockData);

View File

@ -50,6 +50,7 @@ export function handleTest (event: Test): void {
if (!category) { if (!category) {
category = new Category(author.blogCount.toString()); category = new Category(author.blogCount.toString());
category.name = event.params.param1; category.name = event.params.param1;
category.count = BigInt.zero();
} }
category.count = category.count + BigInt.fromString('1'); category.count = category.count + BigInt.fromString('1');
@ -59,13 +60,14 @@ export function handleTest (event: Test): void {
blog.kind = 'long'; blog.kind = 'long';
blog.isActive = true; blog.isActive = true;
const blogReviews = blog.reviews; // eslint-disable-next-line @typescript-eslint/ban-types
const blogReviews: BigInt[] = new Array(0);
blogReviews.push(BigInt.fromString('4')); blogReviews.push(BigInt.fromString('4'));
blog.reviews = blogReviews; blog.reviews = blogReviews;
blog.author = author.id; blog.author = author.id;
const categories = blog.categories; const categories: string[] = new Array(0);
categories.push(category.id); categories.push(category.id);
blog.categories = categories; blog.categories = categories;

View File

@ -102,7 +102,15 @@ export class EthClient implements EthClientInterface {
); );
console.timeEnd(`time:eth-client#getFullBlocks-${JSON.stringify({ blockNumber, blockHash })}`); console.timeEnd(`time:eth-client#getFullBlocks-${JSON.stringify({ blockNumber, blockHash })}`);
return allEthHeaderCids.nodes; return this.addBlockSize(allEthHeaderCids.nodes);
}
// TODO: Get block size from ipld-eth-server
private addBlockSize (nodes: any[]): any[] {
// Populate block size with 0 value
return nodes.map(obj => {
return { ...obj, size: '0' };
});
} }
async getFullTransaction (txHash: string, blockNumber?: number): Promise<EthFullTransaction> { async getFullTransaction (txHash: string, blockNumber?: number): Promise<EthFullTransaction> {

View File

@ -185,7 +185,7 @@ export const processBatchEvents = async (
if (indexer.processBlockAfterEvents) { if (indexer.processBlockAfterEvents) {
if (!dbBlock.isComplete) { if (!dbBlock.isComplete) {
await indexer.processBlockAfterEvents(dbBlock.blockHash, dbBlock.blockNumber); await indexer.processBlockAfterEvents(dbBlock.blockHash, dbBlock.blockNumber, data);
} }
} }

View File

@ -212,7 +212,7 @@ export interface IndexerInterface {
processInitialState: (contractAddress: string, blockHash: string) => Promise<any> processInitialState: (contractAddress: string, blockHash: string) => Promise<any>
processStateCheckpoint: (contractAddress: string, blockHash: string) => Promise<boolean> processStateCheckpoint: (contractAddress: string, blockHash: string) => Promise<boolean>
processBlock: (blockProgres: BlockProgressInterface) => Promise<void> processBlock: (blockProgres: BlockProgressInterface) => Promise<void>
processBlockAfterEvents?: (blockHash: string, blockNumber: number) => Promise<void> processBlockAfterEvents?: (blockHash: string, blockNumber: number, data: ExtraEventData) => Promise<void>
processCanonicalBlock (blockHash: string, blockNumber: number): Promise<void> processCanonicalBlock (blockHash: string, blockNumber: number): Promise<void>
processCheckpoint (blockHash: string): Promise<void> processCheckpoint (blockHash: string): Promise<void>
processCLICheckpoint (contractAddress: string, blockHash?: string): Promise<string | undefined> processCLICheckpoint (contractAddress: string, blockHash?: string): Promise<string | undefined>