Generic Indexing
Generic indexing provides a way to index blockchain events as is without writing specific event handlers. This approach automatically stores events as they appear on-chain, generating all necessary entities, migrations, and documentation from your contract ABIs using a utility package called solidity-events-to-typeorm (opens in a new tab). This is useful if you don't have custom indexing logic for example if you are indexing data to do some data science analysis.
Overview
Instead of writing custom event handlers and entity definitions, generic indexing allows you to:
- Define your contracts and ABIs in the configuration
- Generate entities and migrations using a script
- Index events exactly as they appear on-chain
Getting Started
1. Install Required Dependencies
Add the following to your project:
npm install @open-ethereum/indexer typeorm
npm install -D solidity-events-to-typeorm
2. Configure Generation Script
Create a generation script (typically in scripts/generate.ts
):
import { Config, generate } from 'solidity-events-to-typeorm';
import * as path from 'path';
import ContractABI from '../src/abi/contract.json';
const outputPath = path.resolve(__dirname, './output/');
export const config: Config = {
output: {
path: outputPath,
entities: path.resolve(outputPath, './entities/'),
abis: path.resolve(outputPath, './abi/'),
},
migrations: {
path: path.resolve(outputPath, './migrations/'),
migrationName: 'InitialSchema',
schemaName: 'SQL_SCHEMA',
schemaVariable: true,
},
docs: {
path: path.resolve(outputPath, './docs/'),
},
contracts: {
YourContract: {
abi: ContractABI,
},
},
};
3. Add Generation Script to package.json
Add the generation script to your package.json
:
{
"scripts": {
"generate-entities": "ts-node scripts/generate.ts"
}
}
Run it with npm run generate-entities
to generate the entities and migrations.
4. Configure the Indexer
Create your indexer configuration (src/indexer.config.ts
):
import { IndexerConfig } from '@open-ethereum/indexer';
import ContractABI from './abi/contract.json';
import { InitialSchema } from './output/migrations/InitialSchema';
export const indexerConfig: IndexerConfig = {
indexer: {
network: {
rpcUrl: process.env.NODE_RPC_URL,
chainId: parseInt(process.env.CHAIN_ID),
},
contracts: {
// specify the contracts you specified in the generation script
YourContract: {
abi: ContractABI,
address: '0x...', // Your contract address
startBlock: 1234567,
endBlock: 1234567,
},
},
},
database: {
// the migration that was generated by the script
migrations: [InitialSchema],
},
};
5. Register Entities
Create an entity registration file (src/entity-registration.ts
):
import { entityRegistry } from '@open-ethereum/indexer';
import { GeneratedEntity } from './output/entities/GeneratedEntity';
export const entities = [GeneratedEntity];
// Register all entities
Object.keys(entities).forEach((key) => {
const entity = entities[key];
if (entity && typeof entity === 'function') {
entityRegistry.register(entity);
}
});
How It Works
Generic indexing automatically creates:
- Entities: TypeORM entities that match your contract events
- Migrations: Database schema migrations for your entities
- Documentation: API documentation for your indexed data
You then register entities and migrations with the indexer. It automatically generates a wildcard event handler that indexes the events as they appear on-chain.
Each indexed event will contain standard fields:
uniqueEventId
: Unique identifier for the eventeventOriginAddress
: Contract address that emitted the eventblockNumber
: Block number where the event occurredblockTimestamp
: Timestamp of the blocktransactionHash
: Hash of the transactionlogIndex
: Index of the log in the blocktxIndex
: Transaction index in the blocktopics
: Event topicslogData
: Raw event data
API Access
The generic data is exposed through the automatically generated REST API and GraphQL API.