Handle array and struct type event params in codegen (#150)

* Handle array and struct type event params

* Refactor parse event in watcher indexer code
This commit is contained in:
2022-08-04 17:09:30 +05:30
committed by GitHub
parent a15305450c
commit 6990eb892a
10 changed files with 97 additions and 796 deletions
+1 -31
View File
@@ -8,7 +8,6 @@ import assert from 'assert';
import Handlebars from 'handlebars';
import { Writable } from 'stream';
import _ from 'lodash';
import { utils } from 'ethers';
import { getTsForSol } from './utils/type-mappings';
import { Param } from './utils/types';
@@ -83,31 +82,6 @@ export class Indexer {
this._queries.push(queryObject);
}
addEvent (name: string, params: Array<utils.ParamType>, contractKind: string): void {
// Check if the event is already added.
if (this._events.some(event => event.name === name && event.kind === contractKind)) {
return;
}
const eventObject = {
name,
params: params.map((param) => {
const tsParamType = getTsForSol(param.type);
assert(tsParamType);
const isReferenceType = param.type === 'string' || param.type === 'bytes' || param.baseType === 'tuple' || param.baseType === 'array';
return {
...param,
type: tsParamType,
isIndexedReferenceType: param.indexed && isReferenceType
};
}),
kind: contractKind
};
this._events.push(eventObject);
}
addSubgraphEntities (subgraphSchemaDocument: any): void {
// Add subgraph entities for creating the relations and entity types maps in the indexer.
const subgraphTypeDefs = subgraphSchemaDocument.definitions;
@@ -180,8 +154,6 @@ export class Indexer {
exportIndexer (outStream: Writable, contracts: any[]): void {
const template = Handlebars.compile(this._templateString);
const eventNames = this._events.map((event: any) => event.name);
const obj = {
contracts,
queries: this._queries,
@@ -189,9 +161,7 @@ export class Indexer {
constants: {
MODE_ETH_CALL,
MODE_STORAGE
},
events: this._events,
uniqueEvents: new Set(eventNames)
}
};
const indexer = template(obj);
+51 -22
View File
@@ -4,7 +4,7 @@
import assert from 'assert';
import { GraphQLSchema, parse, printSchema, print } from 'graphql';
import { SchemaComposer } from 'graphql-compose';
import { ObjectTypeComposer, ObjectTypeComposerDefinition, ObjectTypeComposerFieldConfigMapDefinition, SchemaComposer } from 'graphql-compose';
import { Writable } from 'stream';
import { utils } from 'ethers';
@@ -76,27 +76,7 @@ export class Schema {
return;
}
const typeObject: any = {};
typeObject.name = name;
typeObject.fields = {};
if (params.length > 0) {
typeObject.fields = params.reduce((acc, curr) => {
const tsCurrType = getTsForSol(curr.type);
assert(tsCurrType, `ts type for sol type ${curr.type} for ${curr.name} not found`);
acc[curr.name] = `${getGqlForTs(tsCurrType)}!`;
return acc;
}, typeObject.fields);
} else {
// Types must define one or more fields.
typeObject.fields = {
dummy: 'String'
};
}
// Create a type composer to add the required type in the schema composer.
this._composer.createObjectTC(typeObject);
this._createObjectType(name, params);
this._events.push(name);
this._addToEventUnion(name);
@@ -459,4 +439,53 @@ export class Schema {
// Add the new fields to the current type.
eventTC.addFields(newFields);
}
/**
* Create GraphQL schmea object type.
* @param name
* @param params
*/
_createObjectType (name: string, params: Array<utils.ParamType>): ObjectTypeComposer {
const typeObject: ObjectTypeComposerDefinition<any, any> = { name };
if (params.length > 0) {
typeObject.fields = params.reduce((acc: ObjectTypeComposerFieldConfigMapDefinition<any, any>, curr) => {
acc[curr.name] = this._getObjectTypeField(curr);
return acc;
}, {});
} else {
// Types must define one or more fields.
typeObject.fields = {
dummy: 'String'
};
}
// Create a type composer to add the required type in the schema composer.
return this._composer.createObjectTC(typeObject);
}
/**
* Get type of field in GraphQL schema for object types.
* @param param
*/
_getObjectTypeField (param: utils.ParamType): ObjectTypeComposer | string | any[] {
if (param.indexed && ['string', 'bytes', 'tuple', 'array'].includes(param.baseType)) {
// Check for indexed reference type event params.
param = utils.ParamType.fromObject({ type: 'bytes32', name: param.name });
}
if (param.baseType === 'tuple') {
const typeName = param.name.charAt(0).toUpperCase() + param.name.slice(1);
return this._createObjectType(typeName, param.components);
}
if (param.baseType === 'array') {
return [this._getObjectTypeField(param.arrayChildren)];
}
const tsCurrType = getTsForSol(param.type);
assert(tsCurrType, `ts type for sol type ${param.type} for ${param.name} not found`);
return `${getGqlForTs(tsCurrType)}!`;
}
}
@@ -421,7 +421,6 @@ export class Indexer implements IPLDIndexerInterface {
}
{{/if}}
async triggerIndexingOnEvent (event: Event): Promise<void> {
const resultEvent = this.getResultEvent(event);
@@ -450,9 +449,6 @@ export class Indexer implements IPLDIndexerInterface {
}
parseEventNameAndArgs (kind: string, logObj: any): any {
let eventName = UNKNOWN_EVENT_NAME;
let eventInfo = {};
const { topics, data } = logObj;
const contract = this._contractMap.get(kind);
@@ -460,15 +456,7 @@ export class Indexer implements IPLDIndexerInterface {
const logDescription = contract.parseLog({ data, topics });
switch (kind) {
{{#each contracts as | contract |}}
case KIND_{{capitalize contract.contractName}}: {
({ eventName, eventInfo } = this.parse{{contract.contractName}}Event(logDescription));
break;
}
{{/each}}
}
const { eventName, eventInfo } = this._baseIndexer.parseEvent(logDescription)
return {
eventName,
@@ -477,45 +465,6 @@ export class Indexer implements IPLDIndexerInterface {
};
}
{{#each contracts as | contract |}}
parse{{contract.contractName}}Event (logDescription: ethers.utils.LogDescription): { eventName: string, eventInfo: any } {
let eventName = UNKNOWN_EVENT_NAME;
let eventInfo = {};
switch (logDescription.name) {
{{#each ../events as | event |}}
{{#if (compare contract.contractKind event.kind)}}
case {{capitalize event.name}}_EVENT: {
eventName = logDescription.name;
{{#if event.params}}
const [{{#each event.params~}} {{this.name}} {{~#unless @last}}, {{/unless}} {{~/each}}] = logDescription.args;
{{/if}}
eventInfo = {
{{#each event.params}}
{{#if (compare this.type 'bigint')}}
{{this.name}}: BigInt({{this.name}}.toString())
{{~else if this.isIndexedReferenceType}}
{{this.name}}: {{this.name}}.hash
{{~else}}
{{this.name}}
{{~/if}}
{{~#unless @last}},{{/unless}}
{{/each}}
};
break;
}
{{/if}}
{{/each}}
}
return {
eventName,
eventInfo
};
}
{{/each}}
async getIPLDStatus (): Promise<IpldStatus | undefined> {
return this._db.getIPLDStatus();
}
-3
View File
@@ -138,9 +138,6 @@ export class Visitor {
Object.values(contractInterface.events).forEach(event => {
this._schema.addEventType(event.name, event.inputs);
assert(this._contract);
this._indexer.addEvent(event.name, event.inputs, this._contract.kind);
});
}