2021-09-23 11:25:46 +00:00
|
|
|
//
|
|
|
|
// Copyright 2021 Vulcanize, Inc.
|
|
|
|
//
|
|
|
|
|
|
|
|
import fs from 'fs';
|
|
|
|
import path from 'path';
|
|
|
|
import assert from 'assert';
|
2021-09-27 12:33:04 +00:00
|
|
|
import yaml from 'js-yaml';
|
2021-09-23 11:25:46 +00:00
|
|
|
import Handlebars from 'handlebars';
|
|
|
|
import { Writable } from 'stream';
|
|
|
|
|
|
|
|
import { getTsForSol, getPgForTs } from './utils/type-mappings';
|
|
|
|
import { Param } from './utils/types';
|
|
|
|
|
|
|
|
const TEMPLATE_FILE = './templates/entity-template.handlebars';
|
2021-09-27 12:33:04 +00:00
|
|
|
const TABLES_DIR = './data/entities';
|
2021-09-23 11:25:46 +00:00
|
|
|
|
|
|
|
export class Entity {
|
|
|
|
_entities: Array<any>;
|
|
|
|
_templateString: string;
|
|
|
|
|
|
|
|
constructor () {
|
|
|
|
this._entities = [];
|
|
|
|
this._templateString = fs.readFileSync(path.resolve(__dirname, TEMPLATE_FILE)).toString();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates an entity object from the query and stores to be passed to the template.
|
|
|
|
* @param name Name of the query.
|
|
|
|
* @param params Parameters to the query.
|
|
|
|
* @param returnType Return type for the query.
|
|
|
|
*/
|
|
|
|
addQuery (name: string, params: Array<Param>, returnType: string): void {
|
|
|
|
// Check if the query is already added.
|
|
|
|
if (this._entities.some(entity => entity.className.toLowerCase() === name.toLowerCase())) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const entityObject: any = {
|
2021-10-04 05:34:06 +00:00
|
|
|
className: '',
|
2021-09-27 04:43:50 +00:00
|
|
|
indexOn: [],
|
|
|
|
columns: [],
|
|
|
|
imports: []
|
2021-09-23 11:25:46 +00:00
|
|
|
};
|
|
|
|
|
2021-10-04 05:34:06 +00:00
|
|
|
// eth_call mode: Capitalize first letter of entity name (balanceOf -> BalanceOf).
|
|
|
|
// storage mode: Capiltalize second letter of entity name (_balances -> _Balances).
|
|
|
|
entityObject.className = (name.charAt(0) === '_')
|
|
|
|
? `_${name.charAt(1).toUpperCase()}${name.slice(2)}`
|
|
|
|
: `${name.charAt(0).toUpperCase()}${name.slice(1)}`;
|
|
|
|
|
2021-09-27 04:43:50 +00:00
|
|
|
entityObject.imports.push(
|
|
|
|
{
|
2021-09-27 12:33:04 +00:00
|
|
|
toImport: new Set(['Entity', 'PrimaryGeneratedColumn', 'Column', 'Index']),
|
2021-09-27 04:43:50 +00:00
|
|
|
from: 'typeorm'
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
const indexObject = {
|
|
|
|
columns: ['blockHash', 'contractAddress'],
|
|
|
|
unique: true
|
|
|
|
};
|
|
|
|
indexObject.columns = indexObject.columns.concat(
|
|
|
|
params.map((param) => {
|
|
|
|
return param.name;
|
|
|
|
})
|
|
|
|
);
|
|
|
|
entityObject.indexOn.push(indexObject);
|
|
|
|
|
|
|
|
entityObject.columns.push({
|
|
|
|
name: 'blockHash',
|
|
|
|
pgType: 'varchar',
|
|
|
|
tsType: 'string',
|
|
|
|
columnType: 'Column',
|
|
|
|
columnOptions: [
|
|
|
|
{
|
|
|
|
option: 'length',
|
|
|
|
value: 66
|
|
|
|
}
|
|
|
|
]
|
|
|
|
});
|
2021-10-21 07:32:23 +00:00
|
|
|
entityObject.columns.push({
|
|
|
|
name: 'blockNumber',
|
|
|
|
pgType: 'integer',
|
|
|
|
tsType: 'number',
|
|
|
|
columnType: 'Column'
|
|
|
|
});
|
2021-09-27 04:43:50 +00:00
|
|
|
entityObject.columns.push({
|
|
|
|
name: 'contractAddress',
|
|
|
|
pgType: 'varchar',
|
|
|
|
tsType: 'string',
|
|
|
|
columnType: 'Column',
|
|
|
|
columnOptions: [
|
|
|
|
{
|
|
|
|
option: 'length',
|
|
|
|
value: 42
|
|
|
|
}
|
|
|
|
]
|
2021-09-23 11:25:46 +00:00
|
|
|
});
|
|
|
|
|
2021-09-27 04:43:50 +00:00
|
|
|
entityObject.columns = entityObject.columns.concat(
|
|
|
|
params.map((param) => {
|
|
|
|
const name = param.name;
|
2021-09-23 11:25:46 +00:00
|
|
|
|
2021-09-27 04:43:50 +00:00
|
|
|
const tsType = getTsForSol(param.type);
|
|
|
|
assert(tsType);
|
2021-09-23 11:25:46 +00:00
|
|
|
|
2021-09-27 04:43:50 +00:00
|
|
|
const pgType = getPgForTs(tsType);
|
|
|
|
assert(pgType);
|
2021-09-23 11:25:46 +00:00
|
|
|
|
2021-09-27 04:43:50 +00:00
|
|
|
const columnOptions = [];
|
|
|
|
|
|
|
|
if (param.type === 'address') {
|
|
|
|
columnOptions.push(
|
|
|
|
{
|
|
|
|
option: 'length',
|
|
|
|
value: 42
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
|
|
name,
|
|
|
|
pgType,
|
|
|
|
tsType,
|
|
|
|
columnType: 'Column',
|
|
|
|
columnOptions
|
|
|
|
};
|
|
|
|
})
|
|
|
|
);
|
2021-09-23 11:25:46 +00:00
|
|
|
|
|
|
|
const tsReturnType = getTsForSol(returnType);
|
|
|
|
assert(tsReturnType);
|
|
|
|
|
|
|
|
const pgReturnType = getPgForTs(tsReturnType);
|
|
|
|
assert(pgReturnType);
|
|
|
|
|
|
|
|
entityObject.columns.push({
|
|
|
|
name: 'value',
|
|
|
|
pgType: pgReturnType,
|
2021-09-27 04:43:50 +00:00
|
|
|
tsType: tsReturnType,
|
2021-09-27 12:33:04 +00:00
|
|
|
columnType: 'Column',
|
|
|
|
columnOptions: []
|
2021-09-27 04:43:50 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
entityObject.columns.push({
|
|
|
|
name: 'proof',
|
|
|
|
pgType: 'text',
|
|
|
|
tsType: 'string',
|
|
|
|
columnType: 'Column',
|
|
|
|
columnOptions: [
|
|
|
|
{
|
|
|
|
option: 'nullable',
|
|
|
|
value: true
|
|
|
|
}
|
|
|
|
]
|
2021-09-23 11:25:46 +00:00
|
|
|
});
|
|
|
|
|
2021-09-27 12:33:04 +00:00
|
|
|
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'
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2021-09-23 11:25:46 +00:00
|
|
|
this._entities.push(entityObject);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Writes the generated entity files in the given directory.
|
|
|
|
* @param entityDir Directory to write the entities to.
|
|
|
|
*/
|
|
|
|
exportEntities (entityDir: string): void {
|
2021-09-27 04:43:50 +00:00
|
|
|
this._addEventEntity();
|
|
|
|
this._addSyncStatusEntity();
|
|
|
|
this._addContractEntity();
|
|
|
|
this._addBlockProgressEntity();
|
2021-10-12 10:32:56 +00:00
|
|
|
this._addIPLDBlockEntity();
|
2021-10-18 09:20:41 +00:00
|
|
|
this._addHookStatusEntity();
|
2021-09-27 04:43:50 +00:00
|
|
|
|
2021-09-23 11:25:46 +00:00
|
|
|
const template = Handlebars.compile(this._templateString);
|
|
|
|
this._entities.forEach(entityObj => {
|
|
|
|
const entity = template(entityObj);
|
|
|
|
const outStream: Writable = entityDir
|
|
|
|
? fs.createWriteStream(path.join(entityDir, `${entityObj.className}.ts`))
|
|
|
|
: process.stdout;
|
|
|
|
outStream.write(entity);
|
|
|
|
});
|
|
|
|
}
|
2021-09-27 04:43:50 +00:00
|
|
|
|
|
|
|
_addEventEntity (): void {
|
2021-09-27 12:33:04 +00:00
|
|
|
const entity = yaml.load(fs.readFileSync(path.resolve(__dirname, TABLES_DIR, 'Event.yaml'), 'utf8'));
|
2021-09-27 04:43:50 +00:00
|
|
|
this._entities.push(entity);
|
|
|
|
}
|
|
|
|
|
|
|
|
_addSyncStatusEntity (): void {
|
2021-09-27 12:33:04 +00:00
|
|
|
const entity = yaml.load(fs.readFileSync(path.resolve(__dirname, TABLES_DIR, 'SyncStatus.yaml'), 'utf8'));
|
2021-09-27 04:43:50 +00:00
|
|
|
this._entities.push(entity);
|
|
|
|
}
|
|
|
|
|
|
|
|
_addContractEntity (): void {
|
2021-09-27 12:33:04 +00:00
|
|
|
const entity = yaml.load(fs.readFileSync(path.resolve(__dirname, TABLES_DIR, 'Contract.yaml'), 'utf8'));
|
2021-09-27 04:43:50 +00:00
|
|
|
this._entities.push(entity);
|
|
|
|
}
|
|
|
|
|
|
|
|
_addBlockProgressEntity (): void {
|
2021-09-27 12:33:04 +00:00
|
|
|
const entity = yaml.load(fs.readFileSync(path.resolve(__dirname, TABLES_DIR, 'BlockProgress.yaml'), 'utf8'));
|
2021-09-27 04:43:50 +00:00
|
|
|
this._entities.push(entity);
|
|
|
|
}
|
2021-10-12 10:32:56 +00:00
|
|
|
|
|
|
|
_addIPLDBlockEntity (): void {
|
|
|
|
const entity = yaml.load(fs.readFileSync(path.resolve(__dirname, TABLES_DIR, 'IPLDBlock.yaml'), 'utf8'));
|
|
|
|
this._entities.push(entity);
|
|
|
|
}
|
2021-10-14 10:38:45 +00:00
|
|
|
|
2021-10-18 09:20:41 +00:00
|
|
|
_addHookStatusEntity (): void {
|
|
|
|
const entity = yaml.load(fs.readFileSync(path.resolve(__dirname, TABLES_DIR, 'HookStatus.yaml'), 'utf8'));
|
2021-10-14 10:38:45 +00:00
|
|
|
this._entities.push(entity);
|
|
|
|
}
|
2021-09-23 11:25:46 +00:00
|
|
|
}
|