Generic Indexing

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:

  1. Define your contracts and ABIs in the configuration
  2. Generate entities and migrations using a script
  3. 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:

  1. Entities: TypeORM entities that match your contract events
  2. Migrations: Database schema migrations for your entities
  3. 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 event
  • eventOriginAddress: Contract address that emitted the event
  • blockNumber: Block number where the event occurred
  • blockTimestamp: Timestamp of the block
  • transactionHash: Hash of the transaction
  • logIndex: Index of the log in the block
  • txIndex: Transaction index in the block
  • topics: Event topics
  • logData: Raw event data

API Access

The generic data is exposed through the automatically generated REST API and GraphQL API.