> For the complete documentation index, see [llms.txt](https://docs.envio.dev/llms.txt).

# Understanding Generated Indexing Files

## Overview

In V3, the local `generated` package is gone. Code generation now writes a single ambient declaration file at `.envio/types.d.ts` (git-ignored by `.envio/.gitignore`) and wires it into your project through a small `envio-env.d.ts` file at the project root. Everything you used to import from `generated` is now exported from the `envio` package.

These generated declarations form the type-level backbone of your blockchain indexer, translating your configuration, schema, and event handlers into the strongly-typed runtime values exposed by `envio`.

> **Important:** The contents of `.envio/` should never be manually edited. Any changes will be overwritten the next time code generation runs.

## What V3 Emits

| File / location | Purpose |
| --- | --- |
| `.envio/types.d.ts` | Ambient TypeScript declarations describing your contracts, events, entities, enums, and chains. |
| `envio-env.d.ts` (root) | Tiny shim that references `.envio/types.d.ts` so the compiler picks it up. |
| `.envio/.gitignore` | Written once and never overwritten. Ignores `types.d.ts` only. |
| `src/Indexer.res` | ReScript projects only. Exposes the indexer to ReScript handlers. |
| `.envio/cache/` (optional) | Local cache of [Effect API](/docs/HyperIndex/effect-api) results, populated via the dev console. |

The `generated/` directory used by V2 (with ReScript sources, JS shims, and a per-project `package.json`) is no longer produced.

## Purpose of Generated Files

Generated files serve several critical functions:

1. **Type-Safe Data Access** - They provide strongly-typed interfaces to interact with your defined entities through `envio`.
2. **Event Processing** - They describe each contract's events so `indexer.onEvent({ contract, event }, ...)` is fully type-checked.
3. **Database Interactions** - They generate the entity types and helper signatures used by `context.<Entity>` and `indexer.<Entity>`.
4. **Runtime Orchestration** - They feed into the `indexer` value (chains, contracts, entities) that orchestrates indexing.

## Real-World Example: Uniswap V4 Indexer

Let's examine how specific elements from a real Uniswap V4 indexer translate into generated declarations.

### From Schema to Generated Types

For a schema entity like this:

```graphql
type Pool {
  id: ID!
  chainId: BigInt!
  currency0: String!
  currency1: String!
  fee: BigInt!
  tickSpacing: BigInt!
  hooks: String!
  numberOfSwaps: BigInt! @index
  createdAtTimestamp: BigInt!
  createdAtBlockNumber: BigInt!
}
```

The codegen process emits a TypeScript type you can import from `envio`:

```typescript
import type { Entity } from "envio";

// Equivalent to importing the `Pool` named type directly.
type Pool = Entity<"Pool">;

// Shape of the generated entity:
// {
//   id: string;
//   chainId: bigint;
//   currency0: string;
//   currency1: string;
//   fee: bigint;
//   tickSpacing: bigint;
//   hooks: string;
//   numberOfSwaps: bigint;
//   createdAtTimestamp: bigint;
//   createdAtBlockNumber: bigint;
// }
```

You read and write `Pool` entities through the type-safe `context` and `indexer` APIs:

```typescript
// Inside a handler
const pool = await context.Pool.get(id);
context.Pool.set({ id, chainId, currency0, currency1, fee, tickSpacing, hooks, numberOfSwaps, createdAtTimestamp, createdAtBlockNumber });

// Inside a test, on a test indexer from createTestIndexer()
indexer.Pool.set({ /* ... */ });
const stored = await indexer.Pool.getOrThrow(id);
```

### From Config to Generated Event Handlers

Given a contract event in `config.yaml`:

```yaml
contracts:
  - name: PoolManager
    events:
      - event: Swap(bytes32 indexed id, address indexed sender, int128 amount0, int128 amount1, uint160 sqrtPriceX96, uint128 liquidity, int24 tick, uint24 fee)
```

Codegen widens the `indexer.onEvent` overloads so that the following call is fully typed end-to-end (event params, return type, `context.chain`, etc.):

```typescript
import { indexer } from "envio";
import type { EvmEvent } from "envio";

indexer.onEvent(
  { contract: "PoolManager", event: "Swap" },
  async ({ event, context }) => {
    const { id, sender, amount0, amount1, sqrtPriceX96, liquidity, tick, fee } = event.params;
    // ...
  },
);

// The full event payload type is also available as a generic:
type PoolManagerSwapEvent = EvmEvent<"PoolManager", "Swap">;
type PoolManagerSwapBlock = EvmEvent<"PoolManager", "Swap">["block"];
```

### From Multi-Chain Config to Generated Chain Handlers

Your config has multiple chains:

```yaml
chains:
  - id: 1 # Ethereum Mainnet
    # ...
  - id: 10 # Optimism
    # ...
  - id: 42161 # Arbitrum
    # ...
```

Codegen turns the chain set into a literal `EvmChainId` union (`FuelChainId` and `SvmChainId` on other ecosystems) and exposes per-chain helpers under `indexer.chains`:

```typescript
import { indexer } from "envio";
import type { EvmChainId } from "envio";

// EvmChainId is `1 | 10 | 42161`
const mainnet = indexer.chains[1];
const optimism = indexer.chains[10];
const arbitrum = indexer.chains[42161];

// `chain.id` is also typed inside handler/where callbacks:
indexer.onBlock(
  {
    name: "Heartbeat",
    where: ({ chain }) => {
      // chain.id is narrowed to the configured EvmChainId union
      return chain.id === 1;
    },
  },
  async ({ block, context }) => {
    // context.chain.id is typed as well
  },
);
```

`getGeneratedByChainId(...)` from V2 has been replaced by `indexer.chains[chainId]`.

## When to Run Code Generation

You should run code generation using the Envio CLI whenever you:

```bash
pnpm envio codegen
```

Codegen should be run after:

1. Modifying your `config.yaml` file
2. Changing your GraphQL schema
3. Switching to a new contract or ABI
4. After pulling changes from version control

Handler files are not an input to codegen, so editing them doesn't need it.

> Note: changes to handler files in V3 no longer trigger automatic codegen on `pnpm dev`.

## Troubleshooting Generation Errors

When code generation fails, the error points to an issue in `config.yaml`, `schema.graphql` or an ABI. It reads `Failed parsing config`, followed by the specific cause.

### Configuration Errors

A YAML syntax error, a missing required field, an unknown field or a malformed address in `config.yaml` stops codegen. Add the `# yaml-language-server: $schema=./node_modules/envio/evm.schema.json` comment at the top of the file so your editor flags these as you type. See the [Configuration File](/docs/HyperIndex/configuration-file) guide for every field.

### Schema Errors

Schema errors name the entity and field. Common ones:

- `No 'id' field found on entity Pool` - every entity needs an `id`.
- `The [Swap!]! field type requires an explicit @derivedFrom` - a list of entities needs `@derivedFrom`.
- `No type definition 'Int8' exists in schema` - the type isn't a supported scalar, an entity or an enum.
- `Schema contains the following reserved keywords: ...` - rename the entity, enum or enum value.

See the [Schema](/docs/HyperIndex/schema) guide for the full rules.

### Handler Errors

Codegen doesn't read your handlers. Mistakes in them, such as a wrong entity field or an unselected `event.transaction` field, are TypeScript errors. Run `pnpm tsc --noEmit` to see them. From v3.14 the indexer also runs this check on start and won't start until handler files type-check. If `typescript` or a `tsconfig.json` is missing, it logs a warning and skips the check. Import everything from `envio`.

## Relationship with Setup Files

The generated declarations directly reflect the structure defined in your setup files:

- **config.yaml** → Determines which chains, contracts, and events are indexed
- **schema.graphql** → Defines the entities and relationships that are generated
- **handlers in `src/handlers/`** → Provide the business logic that the generated types describe

## Best Practices

1. **Never modify generated files directly** - Always change the source files
2. **Run codegen before starting your indexer** - Ensure all declarations are up to date
3. **Check error messages carefully** - They often pinpoint issues in your setup files
4. **Commit `envio-env.d.ts` and `.envio/.gitignore`** - The shim is part of the project. The `.gitignore` codegen writes keeps `.envio/types.d.ts` out of git and leaves `.envio/cache/` trackable, so you choose whether to commit a saved effect cache.

## Summary

Generated declarations form the critical bridge between your indexing specifications and the actual runtime execution. While you shouldn't modify them directly, understanding their structure and purpose can help you debug issues and optimize your indexing process.

If you encounter persistent errors related to generated files, ensure your configuration, schema, and handlers follow Envio's best practices, or contact support for assistance.

---
