Generate entities from YAML templates and lint support in generated watchers (#253)

* Add lint files generation.

* Fix lint errors in generated code.

* Load default entities from yaml files.

Co-authored-by: prathamesh <prathamesh.musale0@gmail.com>
This commit is contained in:
Ashwin Phatak 2021-09-27 18:03:04 +05:30 committed by GitHub
parent 11d16b9870
commit 338cef9954
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 375 additions and 382 deletions

View File

@ -43,11 +43,19 @@
## Demo ## Demo
* Install required packages: * In root of the repository:
```bash * Install required packages:
yarn
``` ```bash
yarn
```
* Build files:
```bash
yarn build
```
* Generate a watcher from a contract file: * Generate a watcher from a contract file:

View File

@ -24,6 +24,8 @@
"graphql": "^15.5.0", "graphql": "^15.5.0",
"graphql-compose": "^9.0.3", "graphql-compose": "^9.0.3",
"handlebars": "^4.7.7", "handlebars": "^4.7.7",
"js-yaml": "^4.0.0",
"lodash": "^4.17.21",
"node-fetch": "^2", "node-fetch": "^2",
"solc": "^0.8.7-fixed", "solc": "^0.8.7-fixed",
"ts-node": "^10.2.1", "ts-node": "^10.2.1",
@ -32,6 +34,7 @@
}, },
"devDependencies": { "devDependencies": {
"@openzeppelin/contracts": "^4.3.2", "@openzeppelin/contracts": "^4.3.2",
"@types/js-yaml": "^4.0.3",
"@types/node": "^16.9.0", "@types/node": "^16.9.0",
"@typescript-eslint/eslint-plugin": "^4.25.0", "@typescript-eslint/eslint-plugin": "^4.25.0",
"@typescript-eslint/parser": "^4.25.0", "@typescript-eslint/parser": "^4.25.0",

View File

@ -0,0 +1,66 @@
className: BlockProgress
implements: BlockProgressInterface
indexOn:
- columns:
- blockHash
unique: true
- columns:
- blockNumber
- columns:
- parentHash
columns:
- name: blockHash
pgType: varchar
tsType: string
columnType: Column
columnOptions:
- option: length
value: 66
- name: parentHash
pgType: varchar
tsType: string
columnType: Column
columnOptions:
- option: length
value: 66
- name: blockNumber
pgType: integer
tsType: number
columnType: Column
- name: blockTimestamp
pgType: integer
tsType: number
columnType: Column
- name: numEvents
pgType: integer
tsType: number
columnType: Column
- name: numProcessedEvents
pgType: integer
tsType: number
columnType: Column
- name: lastProcessedEventIndex
pgType: integer
tsType: number
columnType: Column
- name: isComplete
pgType: boolean
tsType: boolean
columnType: Column
- name: isPruned
pgType: boolean
tsType: boolean
columnType: Column
columnOptions:
- option: default
value: false
imports:
- toImport:
- Entity
- PrimaryGeneratedColumn
- Column
- Index
from: typeorm
- toImport:
- BlockProgressInterface
from: '@vulcanize/util'

View File

@ -0,0 +1,31 @@
className: Contract
indexOn:
- columns:
- address
unique: true
columns:
- name: address
pgType: varchar
tsType: string
columnType: Column
columnOptions:
- option: length
value: 42
- name: kind
pgType: varchar
tsType: string
columnType: Column
columnOptions:
- option: length
value: 8
- name: startingBlock
pgType: integer
tsType: number
columnType: Column
imports:
- toImport:
- Entity
- PrimaryGeneratedColumn
- Column
- Index
from: typeorm

View File

@ -0,0 +1,63 @@
className: Event
indexOn:
- columns:
- block
- contract
- columns:
- block
- contract
- eventName
columns:
- name: block
tsType: BlockProgress
columnType: ManyToOne
lhs: ()
rhs: BlockProgress
- name: txHash
pgType: varchar
tsType: string
columnType: Column
columnOptions:
- option: length
value: 66
- name: index
pgType: integer
tsType: number
columnType: Column
- name: contract
pgType: varchar
tsType: string
columnType: Column
columnOptions:
- option: length
value: 42
- name: eventName
pgType: varchar
tsType: string
columnType: Column
columnOptions:
- option: length
value: 256
- name: eventInfo
pgType: text
tsType: string
columnType: Column
- name: extraInfo
pgType: text
tsType: string
columnType: Column
- name: proof
pgType: text
tsType: string
columnType: Column
imports:
- toImport:
- Entity
- PrimaryGeneratedColumn
- Column
- Index
- ManyToOne
from: typeorm
- toImport:
- BlockProgress
from: ./BlockProgress

View File

@ -0,0 +1,46 @@
className: SyncStatus
implements: SyncStatusInterface
indexOn: []
columns:
- name: chainHeadBlockHash
pgType: varchar
tsType: string
columnType: Column
columnOptions:
- option: length
value: 66
- name: chainHeadBlockNumber
pgType: integer
tsType: number
columnType: Column
- name: latestIndexedBlockHash
pgType: varchar
tsType: string
columnType: Column
columnOptions:
- option: length
value: 66
- name: latestIndexedBlockNumber
pgType: integer
tsType: number
columnType: Column
- name: latestCanonicalBlockHash
pgType: varchar
tsType: string
columnType: Column
columnOptions:
- option: length
value: 66
- name: latestCanonicalBlockNumber
pgType: integer
tsType: number
columnType: Column
imports:
- toImport:
- Entity
- PrimaryGeneratedColumn
- Column
from: typeorm
- toImport:
- SyncStatusInterface
from: '@vulcanize/util'

View File

@ -5,6 +5,7 @@
import fs from 'fs'; import fs from 'fs';
import path from 'path'; import path from 'path';
import assert from 'assert'; import assert from 'assert';
import yaml from 'js-yaml';
import Handlebars from 'handlebars'; import Handlebars from 'handlebars';
import { Writable } from 'stream'; import { Writable } from 'stream';
@ -12,6 +13,7 @@ import { getTsForSol, getPgForTs } from './utils/type-mappings';
import { Param } from './utils/types'; import { Param } from './utils/types';
const TEMPLATE_FILE = './templates/entity-template.handlebars'; const TEMPLATE_FILE = './templates/entity-template.handlebars';
const TABLES_DIR = './data/entities';
export class Entity { export class Entity {
_entities: Array<any>; _entities: Array<any>;
@ -44,7 +46,7 @@ export class Entity {
entityObject.imports.push( entityObject.imports.push(
{ {
toImport: ['Entity', 'PrimaryGeneratedColumn', 'Column', 'Index'], toImport: new Set(['Entity', 'PrimaryGeneratedColumn', 'Column', 'Index']),
from: 'typeorm' from: 'typeorm'
} }
); );
@ -106,16 +108,6 @@ export class Entity {
); );
} }
// Use bigintTransformer for bigint types.
if (tsType === 'bigint') {
columnOptions.push(
{
option: 'transformer',
value: 'bigintTransformer'
}
);
}
return { return {
name, name,
pgType, pgType,
@ -136,7 +128,8 @@ export class Entity {
name: 'value', name: 'value',
pgType: pgReturnType, pgType: pgReturnType,
tsType: tsReturnType, tsType: tsReturnType,
columnType: 'Column' columnType: 'Column',
columnOptions: []
}); });
entityObject.columns.push({ entityObject.columns.push({
@ -152,6 +145,31 @@ export class Entity {
] ]
}); });
entityObject.columns.forEach((column: any) => {
if (column.tsType === 'bigint') {
column.columnOptions.push(
{
option: 'transformer',
value: 'bigintTransformer'
}
);
const importObject = entityObject.imports.find((element: any) => {
return element.from === '@vulcanize/util';
});
if (importObject) {
importObject.toImport.add('bigintTransformer');
} else {
entityObject.imports.push(
{
toImport: new Set(['bigintTransformer']),
from: '@vulcanize/util'
}
);
}
}
});
this._entities.push(entityObject); this._entities.push(entityObject);
} }
@ -176,362 +194,22 @@ export class Entity {
} }
_addEventEntity (): void { _addEventEntity (): void {
const entity: any = { const entity = yaml.load(fs.readFileSync(path.resolve(__dirname, TABLES_DIR, 'Event.yaml'), 'utf8'));
className: 'Event',
indexOn: [],
columns: [],
imports: []
};
entity.imports.push(
{
toImport: ['Entity', 'PrimaryGeneratedColumn', 'Column', 'Index', 'ManyToOne'],
from: 'typeorm'
},
{
toImport: ['BlockProgress'],
from: './BlockProgress'
}
);
entity.indexOn.push(
{
columns: ['block', 'contract']
},
{
columns: ['block', 'contract', 'eventName']
}
);
entity.columns.push({
name: 'block',
tsType: 'BlockProgress',
columnType: 'ManyToOne',
lhs: '()',
rhs: 'BlockProgress'
});
entity.columns.push({
name: 'txHash',
pgType: 'varchar',
tsType: 'string',
columnType: 'Column',
columnOptions: [
{
option: 'length',
value: 66
}
]
});
entity.columns.push({
name: 'index',
pgType: 'integer',
tsType: 'number',
columnType: 'Column'
});
entity.columns.push({
name: 'contract',
pgType: 'varchar',
tsType: 'string',
columnType: 'Column',
columnOptions: [
{
option: 'length',
value: 42
}
]
});
entity.columns.push({
name: 'eventName',
pgType: 'varchar',
tsType: 'string',
columnType: 'Column',
columnOptions: [
{
option: 'length',
value: 256
}
]
});
entity.columns.push({
name: 'eventInfo',
pgType: 'text',
tsType: 'string',
columnType: 'Column'
});
entity.columns.push({
name: 'extraInfo',
pgType: 'text',
tsType: 'string',
columnType: 'Column'
});
entity.columns.push({
name: 'proof',
pgType: 'text',
tsType: 'string',
columnType: 'Column'
});
this._entities.push(entity); this._entities.push(entity);
} }
_addSyncStatusEntity (): void { _addSyncStatusEntity (): void {
const entity: any = { const entity = yaml.load(fs.readFileSync(path.resolve(__dirname, TABLES_DIR, 'SyncStatus.yaml'), 'utf8'));
className: 'SyncStatus',
implements: 'SyncStatusInterface',
indexOn: [],
columns: [],
imports: []
};
entity.imports.push({
toImport: ['Entity', 'PrimaryGeneratedColumn', 'Column'],
from: 'typeorm'
});
entity.imports.push({
toImport: ['SyncStatusInterface'],
from: '@vulcanize/util'
});
entity.columns.push({
name: 'chainHeadBlockHash',
pgType: 'varchar',
tsType: 'string',
columnType: 'Column',
columnOptions: [
{
option: 'length',
value: 66
}
]
});
entity.columns.push({
name: 'chainHeadBlockNumber',
pgType: 'integer',
tsType: 'number',
columnType: 'Column'
});
entity.columns.push({
name: 'latestIndexedBlockHash',
pgType: 'varchar',
tsType: 'string',
columnType: 'Column',
columnOptions: [
{
option: 'length',
value: 66
}
]
});
entity.columns.push({
name: 'latestIndexedBlockNumber',
pgType: 'integer',
tsType: 'number',
columnType: 'Column'
});
entity.columns.push({
name: 'latestCanonicalBlockHash',
pgType: 'varchar',
tsType: 'string',
columnType: 'Column',
columnOptions: [
{
option: 'length',
value: 66
}
]
});
entity.columns.push({
name: 'latestCanonicalBlockNumber',
pgType: 'integer',
tsType: 'number',
columnType: 'Column'
});
this._entities.push(entity); this._entities.push(entity);
} }
_addContractEntity (): void { _addContractEntity (): void {
const entity: any = { const entity = yaml.load(fs.readFileSync(path.resolve(__dirname, TABLES_DIR, 'Contract.yaml'), 'utf8'));
className: 'Contract',
indexOn: [],
columns: [],
imports: []
};
entity.imports.push({
toImport: ['Entity', 'PrimaryGeneratedColumn', 'Column', 'Index'],
from: 'typeorm'
});
entity.indexOn.push(
{
columns: ['address'],
unique: true
}
);
entity.columns.push({
name: 'address',
pgType: 'varchar',
tsType: 'string',
columnType: 'Column',
columnOptions: [
{
option: 'length',
value: 42
}
]
});
entity.columns.push({
name: 'kind',
pgType: 'varchar',
tsType: 'string',
columnType: 'Column',
columnOptions: [
{
option: 'length',
value: 8
}
]
});
entity.columns.push({
name: 'startingBlock',
pgType: 'integer',
tsType: 'number',
columnType: 'Column'
});
this._entities.push(entity); this._entities.push(entity);
} }
_addBlockProgressEntity (): void { _addBlockProgressEntity (): void {
const entity: any = { const entity = yaml.load(fs.readFileSync(path.resolve(__dirname, TABLES_DIR, 'BlockProgress.yaml'), 'utf8'));
className: 'BlockProgress',
implements: 'BlockProgressInterface',
indexOn: [],
columns: [],
imports: []
};
entity.imports.push({
toImport: ['Entity', 'PrimaryGeneratedColumn', 'Column', 'Index'],
from: 'typeorm'
});
entity.imports.push({
toImport: ['BlockProgressInterface'],
from: '@vulcanize/util'
});
entity.indexOn.push(
{
columns: ['blockHash'],
unique: true
},
{
columns: ['blockNumber']
},
{
columns: ['parentHash']
}
);
entity.columns.push({
name: 'blockHash',
pgType: 'varchar',
tsType: 'string',
columnType: 'Column',
columnOptions: [
{
option: 'length',
value: 66
}
]
});
entity.columns.push({
name: 'parentHash',
pgType: 'varchar',
tsType: 'string',
columnType: 'Column',
columnOptions: [
{
option: 'length',
value: 66
}
]
});
entity.columns.push({
name: 'blockNumber',
pgType: 'integer',
tsType: 'number',
columnType: 'Column'
});
entity.columns.push({
name: 'blockTimestamp',
pgType: 'integer',
tsType: 'number',
columnType: 'Column'
});
entity.columns.push({
name: 'numEvents',
pgType: 'integer',
tsType: 'number',
columnType: 'Column'
});
entity.columns.push({
name: 'numProcessedEvents',
pgType: 'integer',
tsType: 'number',
columnType: 'Column'
});
entity.columns.push({
name: 'lastProcessedEventIndex',
pgType: 'integer',
tsType: 'number',
columnType: 'Column'
});
entity.columns.push({
name: 'isComplete',
pgType: 'boolean',
tsType: 'boolean',
columnType: 'Column'
});
entity.columns.push({
name: 'isPruned',
pgType: 'boolean',
tsType: 'boolean',
columnType: 'Column',
columnOptions: [
{
option: 'default',
value: false
}
]
});
this._entities.push(entity); this._entities.push(entity);
} }
} }

View File

@ -22,6 +22,7 @@ import { exportReadme } from './readme';
import { exportEvents } from './events'; import { exportEvents } from './events';
import { exportJobRunner } from './job-runner'; import { exportJobRunner } from './job-runner';
import { exportWatchContract } from './watch-contract'; import { exportWatchContract } from './watch-contract';
import { exportLint } from './lint';
import { registerHandlebarHelpers } from './utils/handlebar-helpers'; import { registerHandlebarHelpers } from './utils/handlebar-helpers';
const main = async (): Promise<void> => { const main = async (): Promise<void> => {
@ -196,6 +197,17 @@ function generateWatcher (data: string, visitor: Visitor, argv: any) {
? fs.createWriteStream(path.join(outputDir, 'src/cli/watch-contract.ts')) ? fs.createWriteStream(path.join(outputDir, 'src/cli/watch-contract.ts'))
: process.stdout; : process.stdout;
exportWatchContract(outStream); exportWatchContract(outStream);
let rcOutStream;
let ignoreOutStream;
if (outputDir) {
rcOutStream = fs.createWriteStream(path.join(outputDir, '.eslintrc.json'));
ignoreOutStream = fs.createWriteStream(path.join(outputDir, '.eslintignore'));
} else {
rcOutStream = process.stdout;
ignoreOutStream = process.stdout;
}
exportLint(rcOutStream, ignoreOutStream);
} }
main().catch(err => { main().catch(err => {

View File

@ -0,0 +1,28 @@
//
// Copyright 2021 Vulcanize, Inc.
//
import fs from 'fs';
import path from 'path';
import Handlebars from 'handlebars';
import { Writable } from 'stream';
const RC_TEMPLATE_FILE = './templates/eslintrc-template.handlebars';
const IGNORE_TEMPLATE_FILE = './templates/eslintignore-template.handlebars';
/**
* Writes the .eslintrc.json and .eslintignore file generated from a template to respective streams.
* @param rcOutStream A writable output stream to write the .eslintrc.json file to.
* @param ignoreOutStream A writable output stream to write the .eslintignore file to.
*/
export function exportLint (rcOutStream: Writable, ignoreOutStream: Writable): void {
const rcTemplateString = fs.readFileSync(path.resolve(__dirname, RC_TEMPLATE_FILE)).toString();
const rcTemplate = Handlebars.compile(rcTemplateString);
const rcString = rcTemplate({});
rcOutStream.write(rcString);
const ignoreTemplateString = fs.readFileSync(path.resolve(__dirname, IGNORE_TEMPLATE_FILE)).toString();
const ignoreTemplate = Handlebars.compile(ignoreTemplateString);
const ignoreString = ignoreTemplate({});
ignoreOutStream.write(ignoreString);
}

View File

@ -44,6 +44,10 @@ export class Database {
} }
{{#each queries as | query |}} {{#each queries as | query |}}
// eslint-disable-next-line camelcase
{{#if (banTypeCheck (capitalize query.name tillIndex=1)) }}
// eslint-disable-next-line @typescript-eslint/ban-types
{{/if}}
async get{{capitalize query.name tillIndex=1}} ({ blockHash, contractAddress async get{{capitalize query.name tillIndex=1}} ({ blockHash, contractAddress
{{~#each query.params}}, {{this.name~}} {{/each}} }: { blockHash: string, contractAddress: string {{~#each query.params}}, {{this.name~}} {{/each}} }: { blockHash: string, contractAddress: string
{{~#each query.params}}, {{this.name~}}: {{this.type~}} {{/each}} }): Promise<{{capitalize query.name tillIndex=1}} | undefined> { {{~#each query.params}}, {{this.name~}}: {{this.type~}} {{/each}} }): Promise<{{capitalize query.name tillIndex=1}} | undefined> {
@ -54,14 +58,18 @@ export class Database {
{{#each query.params}} {{#each query.params}}
{{this.name}}{{#unless @last}},{{/unless}} {{this.name}}{{#unless @last}},{{/unless}}
{{/each}} {{/each}}
}) });
} }
{{/each}} {{/each}}
{{~#each queries as | query |}} {{~#each queries as | query |}}
// eslint-disable-next-line camelcase
{{#if (banTypeCheck (capitalize query.name tillIndex=1)) }}
// eslint-disable-next-line @typescript-eslint/ban-types
{{/if}}
async save{{capitalize query.name tillIndex=1}} ({ blockHash, contractAddress async save{{capitalize query.name tillIndex=1}} ({ blockHash, contractAddress
{{~#each query.params}}, {{this.name~}} {{/each}}, value, proof}: DeepPartial<{{capitalize query.name tillIndex=1}}>): Promise<{{capitalize query.name tillIndex=1}}> { {{~#each query.params}}, {{this.name~}} {{/each}}, value, proof }: DeepPartial<{{capitalize query.name tillIndex=1}}>): Promise<{{capitalize query.name tillIndex=1}}> {
const repo = this._conn.getRepository({{capitalize query.name tillIndex=1}}); const repo = this._conn.getRepository({{capitalize query.name tillIndex=1}});
const entity = repo.create({ blockHash, contractAddress const entity = repo.create({ blockHash, contractAddress
{{~#each query.params}}, {{this.name~}} {{/each}}, value, proof }); {{~#each query.params}}, {{this.name~}} {{/each}}, value, proof });
@ -184,9 +192,9 @@ export class Database {
}, new Map<string, string>()); }, new Map<string, string>());
} }
_setPropColMaps () { _setPropColMaps (): void {
{{#each queries as | query |}} {{#each queries as | query |}}
this._propColMaps['{{capitalize query.name tillIndex=1}}'] = this._getPropertyColumnMapForEntity('{{capitalize query.name tillIndex=1}}'); this._propColMaps.{{capitalize query.name tillIndex=1}} = this._getPropertyColumnMapForEntity('{{capitalize query.name tillIndex=1}}');
{{/each}} {{/each}}
} }
} }

View File

@ -6,8 +6,6 @@
import { {{~#each import.toImport}} {{this}} {{~#unless @last}}, {{~/unless}} {{~/each}} } from '{{import.from}}'; import { {{~#each import.toImport}} {{this}} {{~#unless @last}}, {{~/unless}} {{~/each}} } from '{{import.from}}';
{{/each}} {{/each}}
import { bigintTransformer } from '@vulcanize/util';
@Entity() @Entity()
{{#each indexOn as | index |}} {{#each indexOn as | index |}}
{{#if index.columns}} {{#if index.columns}}

View File

@ -0,0 +1,2 @@
# Don't lint build output.
dist

View File

@ -0,0 +1,27 @@
{
"env": {
"browser": true,
"es2021": true
},
"extends": [
"semistandard",
"plugin:@typescript-eslint/recommended"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 12,
"sourceType": "module"
},
"plugins": [
"@typescript-eslint"
],
"rules": {
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/explicit-module-boundary-types": [
"warn",
{
"allowArgumentsExplicitlyTypedAsAny": true
}
]
}
}

View File

@ -7,11 +7,11 @@ import debug from 'debug';
import { JsonFragment } from '@ethersproject/abi'; import { JsonFragment } from '@ethersproject/abi';
import { DeepPartial } from 'typeorm'; import { DeepPartial } from 'typeorm';
import JSONbig from 'json-bigint'; import JSONbig from 'json-bigint';
import { BigNumber, ethers } from 'ethers'; import { ethers } from 'ethers';
import { BaseProvider } from '@ethersproject/providers'; import { BaseProvider } from '@ethersproject/providers';
import { EthClient } from '@vulcanize/ipld-eth-client'; import { EthClient } from '@vulcanize/ipld-eth-client';
import { getStorageValue, GetStorageAt, StorageLayout } from '@vulcanize/solidity-mapper'; import { StorageLayout } from '@vulcanize/solidity-mapper';
import { EventInterface, Indexer as BaseIndexer, ValueResult, UNKNOWN_EVENT_NAME } from '@vulcanize/util'; import { EventInterface, Indexer as BaseIndexer, ValueResult, UNKNOWN_EVENT_NAME } from '@vulcanize/util';
import { Database } from './database'; import { Database } from './database';
@ -101,7 +101,6 @@ export class Indexer {
{{#each queries as | query |}} {{#each queries as | query |}}
async {{query.name}} (blockHash: string, contractAddress: string async {{query.name}} (blockHash: string, contractAddress: string
{{~#each query.params}}, {{this.name~}}: {{this.type~}} {{/each}}): Promise<ValueResult> { {{~#each query.params}}, {{this.name~}}: {{this.type~}} {{/each}}): Promise<ValueResult> {
const entity = await this._db.get{{capitalize query.name tillIndex=1}}({ blockHash, contractAddress const entity = await this._db.get{{capitalize query.name tillIndex=1}}({ blockHash, contractAddress
{{~#each query.params}}, {{this.name~}} {{~/each}} }); {{~#each query.params}}, {{this.name~}} {{~/each}} });
if (entity) { if (entity) {
@ -119,21 +118,22 @@ export class Indexer {
const contract = new ethers.Contract(contractAddress, this._abi, this._ethProvider); const contract = new ethers.Contract(contractAddress, this._abi, this._ethProvider);
const { block: { number } } = await this._ethClient.getBlockByHash(blockHash); const { block: { number } } = await this._ethClient.getBlockByHash(blockHash);
const blockNumber = BigNumber.from(number).toNumber(); const blockNumber = ethers.BigNumber.from(number).toNumber();
{{#if (compare query.returnType 'bigint')}}
let value = await contract.{{query.name}}( let value = await contract.{{query.name}}(
{{~#each query.params}}{{this.name}}, {{/each}}{ blockTag: blockNumber }); {{~#each query.params}}{{this.name}}, {{/each}}{ blockTag: blockNumber });
{{~#if (compare query.returnType 'bigint')}}
value = value.toString(); value = value.toString();
value = BigInt(value); value = BigInt(value);
{{else}}
const value = await contract.{{query.name}}(
{{~#each query.params}}{{this.name}}, {{/each}}{ blockTag: blockNumber });
{{/if}} {{/if}}
const result: ValueResult = { value }; const result: ValueResult = { value };
{{/if}} {{/if}}
{{~#if (compare query.mode @root.constants.MODE_STORAGE)}} {{~#if (compare query.mode @root.constants.MODE_STORAGE)}}
const result = await this._baseIndexer.getStorageValue( const result = await this._baseIndexer.getStorageValue(
this._storageLayout, this._storageLayout,
blockHash, blockHash,
@ -152,9 +152,9 @@ export class Indexer {
} }
{{/each}} {{/each}}
async triggerIndexingOnEvent (event: Event): Promise<void> { async triggerIndexingOnEvent (event: Event): Promise<void> {
// TODO: Implement custom hooks. // TODO: Implement custom hooks.
assert(event);
} }
async processEvent (event: Event): Promise<void> { async processEvent (event: Event): Promise<void> {

View File

@ -5,6 +5,7 @@
"private": true, "private": true,
"main": "dist/index.js", "main": "dist/index.js",
"scripts": { "scripts": {
"lint": "eslint .",
"build": "tsc", "build": "tsc",
"server": "DEBUG=vulcanize:* ts-node src/server.ts", "server": "DEBUG=vulcanize:* ts-node src/server.ts",
"job-runner": "DEBUG=vulcanize:* ts-node src/job-runner.ts", "job-runner": "DEBUG=vulcanize:* ts-node src/job-runner.ts",
@ -21,7 +22,7 @@
}, },
"homepage": "https://github.com/vulcanize/watcher-ts#readme", "homepage": "https://github.com/vulcanize/watcher-ts#readme",
"dependencies": { "dependencies": {
"@apollo/client": "^3.3.19", "@ethersproject/providers": "5.3.0",
"@vulcanize/cache": "^0.1.0", "@vulcanize/cache": "^0.1.0",
"@vulcanize/ipld-eth-client": "^0.1.0", "@vulcanize/ipld-eth-client": "^0.1.0",
"@vulcanize/solidity-mapper": "^0.1.0", "@vulcanize/solidity-mapper": "^0.1.0",
@ -33,13 +34,24 @@
"express": "^4.17.1", "express": "^4.17.1",
"graphql": "^15.5.0", "graphql": "^15.5.0",
"graphql-import-node": "^0.0.4", "graphql-import-node": "^0.0.4",
"json-bigint": "^1.0.0",
"reflect-metadata": "^0.1.13", "reflect-metadata": "^0.1.13",
"typeorm": "^0.2.32",
"yargs": "^17.0.1" "yargs": "^17.0.1"
}, },
"devDependencies": { "devDependencies": {
"@ethersproject/abi": "^5.3.0", "@ethersproject/abi": "^5.3.0",
"@types/express": "^4.17.11", "@types/express": "^4.17.11",
"@types/yargs": "^17.0.0", "@types/yargs": "^17.0.0",
"@typescript-eslint/eslint-plugin": "^4.25.0",
"@typescript-eslint/parser": "^4.25.0",
"eslint": "^7.27.0",
"eslint-config-semistandard": "^15.0.1",
"eslint-config-standard": "^16.0.3",
"eslint-plugin-import": "^2.23.3",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^5.1.0",
"eslint-plugin-standard": "^5.0.0",
"ts-node": "^10.0.0", "ts-node": "^10.0.0",
"typescript": "^4.3.2" "typescript": "^4.3.2"
} }

View File

@ -5,9 +5,12 @@
import assert from 'assert'; import assert from 'assert';
import Handlebars from 'handlebars'; import Handlebars from 'handlebars';
import { bannedTypes } from './types';
export function registerHandlebarHelpers (): void { export function registerHandlebarHelpers (): void {
Handlebars.registerHelper('compare', compareHelper); Handlebars.registerHelper('compare', compareHelper);
Handlebars.registerHelper('capitalize', capitalizeHelper); Handlebars.registerHelper('capitalize', capitalizeHelper);
Handlebars.registerHelper('banTypeCheck', banTypeCheckHelper);
} }
/** /**
@ -50,3 +53,7 @@ function capitalizeHelper (value: string, options: any): string {
return result; return result;
} }
function banTypeCheckHelper (value: string): boolean {
return bannedTypes.has(value);
}

View File

@ -6,3 +6,7 @@ export interface Param {
name: string; name: string;
type: string; type: string;
} }
export const bannedTypes = new Set([
'Symbol'
]);

View File

@ -40,6 +40,7 @@
"homepage": "https://github.com/vulcanize/watcher-ts#readme", "homepage": "https://github.com/vulcanize/watcher-ts#readme",
"dependencies": { "dependencies": {
"@apollo/client": "^3.3.19", "@apollo/client": "^3.3.19",
"@ethersproject/providers": "5.3.0",
"@types/lodash": "^4.14.168", "@types/lodash": "^4.14.168",
"@vulcanize/cache": "^0.1.0", "@vulcanize/cache": "^0.1.0",
"@vulcanize/ipld-eth-client": "^0.1.0", "@vulcanize/ipld-eth-client": "^0.1.0",
@ -63,7 +64,6 @@
"@ethersproject/abi": "^5.3.0", "@ethersproject/abi": "^5.3.0",
"@nomiclabs/hardhat-ethers": "^2.0.2", "@nomiclabs/hardhat-ethers": "^2.0.2",
"@nomiclabs/hardhat-waffle": "^2.0.1", "@nomiclabs/hardhat-waffle": "^2.0.1",
"@openzeppelin/contracts": "^4.3.1",
"@types/express": "^4.17.11", "@types/express": "^4.17.11",
"@types/json-bigint": "^1.0.0", "@types/json-bigint": "^1.0.0",
"@types/yargs": "^17.0.0", "@types/yargs": "^17.0.0",

View File

@ -1979,11 +1979,6 @@
resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-3.4.1-solc-0.7-2.tgz#371c67ebffe50f551c3146a9eec5fe6ffe862e92" resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-3.4.1-solc-0.7-2.tgz#371c67ebffe50f551c3146a9eec5fe6ffe862e92"
integrity sha512-tAG9LWg8+M2CMu7hIsqHPaTyG4uDzjr6mhvH96LvOpLZZj6tgzTluBt+LsCf1/QaYrlis6pITvpIaIhE+iZB+Q== integrity sha512-tAG9LWg8+M2CMu7hIsqHPaTyG4uDzjr6mhvH96LvOpLZZj6tgzTluBt+LsCf1/QaYrlis6pITvpIaIhE+iZB+Q==
"@openzeppelin/contracts@^4.3.1":
version "4.3.1"
resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.3.1.tgz#c01f791ce6c9d3989ac1a643267501dbe336b9e3"
integrity sha512-QjgbPPlmDK2clK1hzjw2ROfY8KA5q+PfhDUUxZFEBCZP9fi6d5FuNoh/Uq0oCTMEKPmue69vhX2jcl0N/tFKGw==
"@openzeppelin/contracts@^4.3.2": "@openzeppelin/contracts@^4.3.2":
version "4.3.2" version "4.3.2"
resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.3.2.tgz#ff80affd6d352dbe1bbc5b4e1833c41afd6283b6" resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.3.2.tgz#ff80affd6d352dbe1bbc5b4e1833c41afd6283b6"
@ -2400,6 +2395,11 @@
resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-1.8.0.tgz#682477dbbbd07cd032731cb3b0e7eaee3d026b69" resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-1.8.0.tgz#682477dbbbd07cd032731cb3b0e7eaee3d026b69"
integrity sha512-2aoSC4UUbHDj2uCsCxcG/vRMXey/m17bC7UwitVm5hn22nI8O8Y9iDpA76Orc+DWkQ4zZrOKEshCqR/jSuXAHA== integrity sha512-2aoSC4UUbHDj2uCsCxcG/vRMXey/m17bC7UwitVm5hn22nI8O8Y9iDpA76Orc+DWkQ4zZrOKEshCqR/jSuXAHA==
"@types/js-yaml@^4.0.3":
version "4.0.3"
resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-4.0.3.tgz#9f33cd6fbf0d5ec575dc8c8fc69c7fec1b4eb200"
integrity sha512-5t9BhoORasuF5uCPr+d5/hdB++zRFUTMIZOzbNkr+jZh3yQht4HYbRDyj9fY8n2TZT30iW9huzav73x4NikqWg==
"@types/json-bigint@^1.0.0": "@types/json-bigint@^1.0.0":
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/@types/json-bigint/-/json-bigint-1.0.0.tgz#7a4726540cc6fe47cfa54b9b3022b89cf7fe1517" resolved "https://registry.yarnpkg.com/@types/json-bigint/-/json-bigint-1.0.0.tgz#7a4726540cc6fe47cfa54b9b3022b89cf7fe1517"