HyperIndex Complete Documentation
This document contains all HyperIndex documentation consolidated into a single file for LLM consumption.
Overviewβ
File: overview.md
HyperIndex is a blazing-fast, developer-friendly multichain indexer, optimized for both local development and reliable hosted deployment. It empowers developers to effortlessly build robust backends for blockchain applications.
!Sync Process
HyperIndex is Envio's full-featured blockchain indexing framework that transforms on-chain events into structured, queryable databases with GraphQL APIs.
HyperSync is the high-performance data engine that powers HyperIndex. It provides the raw blockchain data access layer, delivering up to 2000x faster performance than traditional RPC endpoints.
While HyperIndex gives you a complete indexing solution with schema management and event handling, HyperSync can be used directly for custom data pipelines and specialized applications.
HyperSync API Token Requirementsβ
HyperSync (the data engine powering HyperIndex) implements rate limits for requests without API tokens. API tokens will be required from 3 November 2025. Here's what you need to know:
- Local Development: An API token will be required. An automatic login feature from the CLI will be available to make this smoother.
- Self-Hosted Deployments: API tokens are required for HyperSync access in self-hosted deployments. The token can be set via the
ENVIO_API_TOKENenvironment variable in your indexer configuration. This can be read from the.envfile in the root of your HyperIndex project. - Hosted Service: Indexers deployed to our hosted service will have special access that doesn't require a custom API token.
- Future Pricing: From mid-November 2025 onwards, we will introduce tiered packages for those self-hosting HyperIndex and wishing to use HyperSync. For preferred introductory pricing based on your specific use case, reach out to us on Discord.
For more details about API tokens, including how to generate and implement them, see our API Tokens documentation.
π Quick Linksβ
- GitHub Repository β
- Join our Discord Community
Getting Startedβ
File: getting-started.md
Learn how to create and run a blockchain indexer with Envioβs HyperIndex, from initialization to local testing and deployment.
Indexer Initializationβ
Prerequisitesβ
- Node.js (v22 or newer recommended)
- pnpm (v8 or newer)
- Docker Desktop (required to run the Envio indexer locally)
Note: Docker is required only if you plan to run your indexer locally. You can skip installing Docker if you'll only be using Envio's Hosted Service.
Additionally for Windows Users:β
- WSL Windows Subsystem for Linux
Essential Filesβ
After initialization, your indexer will contain three main files that are essential for its operation:
config.yamlβ Defines indexing settings such as blockchain endpoints, events to index, and advanced behaviors.schema.graphqlβ Defines the GraphQL schema for indexed data and its structure for efficient querying.src/EventHandlers.*β Contains the logic for processing blockchain events.
Note: The file extension for Event Handlers (
*.ts,*.js, or*.res) depends on the programming language chosen (TypeScript, JavaScript, or ReScript).
You can customize your indexer by modifying these files to meet your specific requirements.
For a complete walkthrough of the process, refer to the Quickstart guide.
Contract Importβ
File: contract-import.md
The Quickstart enables you to instantly autogenerate a powerful blockchain indexer and start querying blockchain data in minutes. This is the fastest and easiest way to begin using HyperIndex.
Example: Autogenerate an indexer for the Eigenlayer contract and index its entire history in less than 5 minutes by simply running pnpx envio init and providing the contract address from Etherscan.
Video Tutorialsβ
Contract Import Methodsβ
There are two convenient methods to import your contract:
- Block Explorer (verified contracts on supported explorers like Etherscan and Blockscout)
- Local ABI (custom or unverified contracts)
1. Block Explorer Importβ
This method uses a verified contract's address from a supported blockchain explorer (Etherscan, Routescan, etc.) to automatically fetch the ABI.
Steps:β
a. Select the blockchain
? Which blockchain would you like to import a contract from?
> ethereum-mainnet
goerli
optimism
base
bsc
gnosis
polygon
[ββ to move, enter to select]
HyperIndex supports all EVM-compatible chains. If your desired chain is not listed, you can import via the local ABI method or manually adjust the config.yaml file after initialization.
b. Enter the contract address
? What is the address of the contract?
[Use proxy address if ABI is for a proxy implementation]
If using a proxy contract, always specify the proxy address, not the implementation address.
c. Select events to index
? Which events would you like to index?
> [x] ClaimRewards(address indexed from, address indexed reward, uint256 amount)
[x] Deposit(address indexed from, uint256 indexed tokenId, uint256 amount)
[x] NotifyReward(address indexed from, address indexed reward, uint256 indexed epoch, uint256 amount)
[x] Withdraw(address indexed from, uint256 indexed tokenId, uint256 amount)
[space to select, β to select all, β to deselect all]
d. Finish or add more contracts
You'll be prompted to continue adding more contracts or to complete the setup:
? Would you like to add another contract?
> I'm finished
Add a new address for same contract on same network
Add a new network for same contract
Add a new contract (with a different ABI)
Generated Files & Configurationβ
The Quickstart automatically generates key files:
1. config.yamlβ
Automatically configured parameters include:
- Network ID
- Start Block
- Contract Name
- Contract Address
- Event Signatures
By default, all selected events are included, but you can manually adjust the file if needed. See the detailed guide on config.yaml.
2. GraphQL Schemaβ
- Entities are automatically generated for each selected event.
- Fields match the event parameters emitted.
See more details in the schema file guide.
3. Event Handlersβ
- Handlers are autogenerated for each event.
- Handlers create event-specific entities.
Learn more in the event handlers guide.
HyperIndex Performance Benchmarksβ
File: benchmarks.md
Overviewβ
HyperIndex delivers industry-leading performance for blockchain data indexing. Independent benchmarks have consistently shown Envio's HyperIndex to be the fastest blockchain indexing solution available, with dramatic performance advantages over competitive offerings.
Recent Independent Benchmarksβ
The most comprehensive and up-to-date benchmarks were conducted by Sentio in April 2025 and are available in the sentio-benchmark repository. These benchmarks compare Envio's HyperIndex against other popular blockchain indexers across multiple real-world scenarios:
Key Performance Highlightsβ
| Case | Description | Envio | Nearest Competitor | The Graph | Ponder |
|---|---|---|---|---|---|
| LBTC Token Transfers | Event handling, No RPC calls, Write-only | 3m | 8m - 2.6x slower (Sentio) | 3h9m - 3780x slower | 1h40m - 2000x slower |
| LBTC Token with RPC calls | Event handling, RPC calls, Read-after-write | 1m | 6m - 6x slower (Sentio) | 1h3m - 63x slower | 45m - 45x slower |
| Ethereum Block Processing | 100K blocks with Metadata extraction | 7.9s | 1m - 7.5x slower (Subsquid) | 10m - 75x slower | 33m - 250x slower |
| Ethereum Transaction Gas Usage | Transaction handling, Gas calculations | 1m 26s | 7m - 4.8x slower (Subsquid) | N/A | 33m - 23x slower |
| Uniswap V2 Swap Trace Analysis | Transaction trace handling, Swap decoding | 41s | 2m - 3x slower (Subsquid) | 8m - 11x slower | N/A |
| Uniswap V2 Factory | Event handling, Pair and swap analysis | 8s | 2m - 15x slower (Subsquid) | 19m - 142x slower | 21m - 157x slower |
The independent benchmark results demonstrate that HyperIndex consistently outperforms all competitors across every tested scenario. This includes the most realistic real-world indexing scenario LBTC Token with RPC calls - where HyperIndex was up to 6x faster than the nearest competitor and over 63x faster than The Graph.
Historical Benchmarking Resultsβ
Our internal benchmarking from October 2023 showed similar performance advantages. When indexing the Uniswap V3 ETH-USDC pool contract on Ethereum Mainnet, HyperIndex achieved:
- 2.1x faster indexing than the nearest competitor
- Over 100x faster indexing than some popular alternatives
You can read the full details in our Indexer Benchmarking Results blog post.
Verify For Yourselfβ
We encourage developers to run their own benchmarks. You can use the templates provided in the Sentio benchmark repository or our sample indexer implementations for various scenarios.
Migrate from The Graph to Envioβ
File: migration-guide.md
Please reach out to our team on Discord for personalized migration assistance.
Introductionβ
Migrating your existing subgraph to Envio's HyperIndex is designed to be a developer-friendly process. HyperIndex draws strong inspiration from The Graphβs subgraph architecture, which makes the migration simple, especially with the help of coding assistants like Cursor and AI tools (don't forget to use our ai friendly docs).
The process is simple but requires a good understanding of the underlying concepts. If you are new to HyperIndex, we recommend starting with the Getting Started guide.
Why Migrate to HyperIndex?β
- Superior Performance: Up to 100x faster indexing speeds
- Lower Costs: Reduced infrastructure requirements and operational expenses
- Better Developer Experience: Simplified configuration and deployment
- Advanced Features: Access to capabilities not available in other indexing solutions
- Seamless Integration: Easy integration with existing GraphQL APIs and applications
Subgraph to HyperIndex Migration Overviewβ
Migration consists of three major steps:
- Subgraph.yaml migration
- Schema migration - near copy paste
- Event handler migration
At any point in the migration run
pnpm envio codegen
to verify the config.yaml and schema.graphql files are valid.
or run
pnpm dev
to verify the indexer is running and indexing correctly.
0.5 Use npx envio init to generate a boilerplateβ
As a first step, we recommend using npx envio init to generate a boilerplate for your project. This will handle the creation of the config.yaml file and a basic schema.graphql file with generic handler functions.
1. subgraph.yaml β config.yamlβ
npx envio init will generate this for you. It's a simple configuration file conversion. Effectively specifying which contracts to index, which networks to index (multiple networks can be specified with envio) and which events from those contracts to index.
Take the following conversion as an example, where the subgraph.yaml file is converted to config.yaml the below comparisons is for the Uniswap v4 pool manager subgraph.
The Graph - subgraph.yaml
specVersion: 0.0.4
description: Uniswap is a decentralized protocol for automated token exchange on Ethereum.
repository: https://github.com/Uniswap/v4-subgraph
schema:
file: ./schema.graphql
features:
- nonFatalErrors
- grafting
- kind: ethereum/contract
name: PositionManager
network: mainnet
source:
abi: PositionManager
address: "0xbD216513d74C8cf14cf4747E6AaA6420FF64ee9e"
startBlock: 21689089
mapping:
kind: ethereum/events
apiVersion: 0.0.7
language: wasm/assemblyscript
file: ./src/mappings/index.ts
entities:
- Position
abis:
- name: PositionManager
file: ./abis/PositionManager.json
eventHandlers:
- event: Subscription(indexed uint256,indexed address)
handler: handleSubscription
- event: Unsubscription(indexed uint256,indexed address)
handler: handleUnsubscription
- event: Transfer(indexed address,indexed address,indexed uint256)
handler: handleTransfer
HyperIndex - config.yaml
# yaml-language-server: $schema=./node_modules/envio/evm.schema.json
name: uni-v4-indexer
networks:
- id: 1
start_block: 21689089
contracts:
- name: PositionManager
address: 0xbD216513d74C8cf14cf4747E6AaA6420FF64ee9e
handler: src/EventHandlers.ts
events:
- event: Subscription(uint256 indexed tokenId, address indexed subscriber)
- event: Unsubscription(uint256 indexed tokenId, address indexed subscriber)
- event: Transfer(address indexed from, address indexed to, uint256 indexed id)
For any potential hurdles, please refer to the Configuration File documentation.
2. Schema migrationβ
copy & paste the schema from the subgraph to the HyperIndex config file.
Small nuance differences:
- You can remove the
@entitydirective - Enums
- BigDecimals
3. Event handler migrationβ
This consists of two parts
- Converting assemblyscript to typescript
- Converting the subgraph syntax to HyperIndex syntax
3.1 Converting Assemblyscript to Typescriptβ
The subgraph uses assemblyscript to write event handlers. The HyperIndex syntax is usually in typescript. Since assemblyscript is a subset of typescript, it's quite simple to copy and paste the code, especially so for pure functions.
3.2 Converting the subgraph syntax to HyperIndex syntaxβ
There are some subtle differences in the syntax of the subgraph and HyperIndex. Including but not limited to the following:
- Replace Entity.save() with context.Entity.set()
- Convert to async handler functions
- Use
awaitfor loading entitiesconst x = await context.Entity.get(id) - Use dynamic contract registration to register contracts
The below code snippets can give you a basic idea of what this difference might look like.
The Graph - eventHandler.ts
export function handleSubscription(event: SubscriptionEvent): void {
const subscription = new Subscribe(event.transaction.hash + event.logIndex);
subscription.tokenId = event.params.tokenId;
subscription.address = event.params.subscriber.toHexString();
subscription.logIndex = event.logIndex;
subscription.blockNumber = event.block.number;
subscription.position = event.params.tokenId;
subscription.save();
}
HyperIndex - eventHandler.ts
PoolManager.Subscription.handler( async (event, context) => {
const entity = {
id: event.transaction.hash + event.logIndex,
tokenId: event.params.tokenId,
address: event.params.subscriber,
blockNumber: event.block.number,
logIndex: event.logIndex,
position: event.params.tokenId
}
context.Subscription.set(entity);
})
Extra tipsβ
HyperIndex is a powerful tool that can be used to index any contract. There are some features that are especially powerful that go above subgraph implementations and so in some cases you may want to optimise your migration to HyperIndex further to take advantage of these features. Here are some useful tips:
- Use the
field_selectionoption to add additional fields to your index. Doc here: field selection - Use the
unordered_multichain_modeoption to enable unordered multichain mode, this is the most common need for multichain indexing. However comes with tradeoffs worth understanding. Doc here: unordered multichain mode - Use wildcard indexing to index by event signatures rather than by contract address.
- HyperIndex uses the standard GraphQL query language, whereas TheGraph uses a custom GraphQL syntax. You can read about the differences and how to convert queries in our Query Conversion Guide. We also provide a query converter tool for backwards compatibility with existing TheGraph queries.
- Loaders are a powerful feature to optimize historical sync performance. You can read more about them here.
- HyperIndex is very flexible and can be used to index offchain data too or send messages to a queue etc for fetching external data, you can further optimise the fetching by using the effects api
Validating Your Migrationβ
After completing your migration, it's important to verify that your HyperIndex indexer produces the same data as your original subgraph. Use the Indexer Migration Validator CLI tool to compare results between both endpoints and identify any discrepancies. The tool automatically generates entity configs from your GraphQL schema and provides detailed field-level analysis of differences.
Share Your Learningsβ
If you discover helpful tips during your migration, we'd love contributions! Open a PR to this guide and help future developers.
Getting Helpβ
Join Our Discord: The fastest way to get personalized help is through our Discord community.
---
## Migrate From Alchemy
**File:** `migrate-from-alchemy.md`
:::note
Note: Alchemy subgraphs sunset on Dec 8th, 2025. Envio is offering affected Alchemy users 2 months of free hosting on Envio, along with full white-glove migration support to help projects move over smoothly.
For more info on how you can start your free trial or book migration support, visit this page to learn more.
:::
Migrating Alchemy subgraphs to Envioβs HyperIndex is a simple and developer-friendly process. Alchemy subgraphs follow The Graphβs model and HyperIndex uses a very similar structure, so most of your existing setup can carry over cleanly.
If you're familiar with The Graphβs libraries, the migration process should be straightforward. You can also utilize tools like Cursor to speed things up. If you are new to HyperIndex, we strongly recommend starting with our Getting Started guide before you begin your migration from Alchemy.
## Why Migrate to Envioβs HyperIndex?
- **High Speed Performance**: 143x faster than subgraphs
- **Lower Costs**: Reduced infrastructure requirements and operational expenses
- **Better Developer Experience**: Simplified configuration and deployment
- **Multichain Native**: Index data across multiple EVM chains through a single HyperIndex project
- **Local Development**: Run your indexers locally for fast iteration and easier debugging
- **White Glove Migration Support**: Get direct support from the Envio team for a smoother migration.
- **GitOps Ready Deployments**: Link your GitHub repo and manage multiple deployments in a clean unified workflow
- **Advanced Features**: Access to features like external calls and block handlers
- **Seamless Integration**: Easily integrate existing GraphQL APIs and applications
## How to Migrate from Alchemy to Envio in 4 easy steps
This Migration consists of 4 major steps:
1. Create a HyperIndex Project
2. subgraph.yaml Migration to config.yaml
3. schema.graphql Migration
4. Event Handler Migration
### Create a HyperIndex Project
Start by spinning up a basic HyperIndex project with this command:
```bash
pnpx envio init template --name alchemy-migration --directory alchemy-migration --template greeter --api-token "YOUR_ENVIO_API_KEY"
Once the project is created, drop your API key into the .env file and youβre good to go.
subgraph.yaml Migration to config.yamlβ
In HyperIndex, all project configuration lives in config.yaml. This is where you define contract addresses, the networks you want to index, and the specific events you want to track from those contracts.
Below is an example showing how a Uniswap V4 subgraph.yaml maps to a HyperIndex config.yaml in a real migration.
The Graph - subgraph.yaml
specVersion: 0.0.4
description: Uniswap is a decentralized protocol for automated token exchange on Ethereum.
repository: https://github.com/Uniswap/v4-subgraph
schema:
file: ./schema.graphql
features:
- nonFatalErrors
- grafting
- kind: ethereum/contract
name: PositionManager
network: mainnet
source:
abi: PositionManager
address: "0xbD216513d74C8cf14cf4747E6AaA6420FF64ee9e"
startBlock: 21689089
mapping:
kind: ethereum/events
apiVersion: 0.0.7
language: wasm/assemblyscript
file: ./src/mappings/index.ts
entities:
- Position
abis:
- name: PositionManager
file: ./abis/PositionManager.json
eventHandlers:
- event: Subscription(indexed uint256,indexed address)
handler: handleSubscription
- event: Unsubscription(indexed uint256,indexed address)
handler: handleUnsubscription
- event: Transfer(indexed address,indexed address,indexed uint256)
handler: handleTransfer
HyperIndex - config.yaml
# yaml-language-server: $schema=./node_modules/envio/evm.schema.json
name: uni-v4-indexer
networks:
- id: 1
start_block: 21689089
contracts:
- name: PositionManager
address: 0xbD216513d74C8cf14cf4747E6AaA6420FF64ee9e
handler: src/EventHandlers.ts
events:
- event: Subscription(uint256 indexed tokenId, address indexed subscriber)
- event: Unsubscription(uint256 indexed tokenId, address indexed subscriber)
- event: Transfer(address indexed from, address indexed to, uint256 indexed id)
If you hit any issues, check the Configuration File docs or reach out to our team in Discord.
schema.graphql Migrationβ
This step is simple. You keep the entire file as is, with one small change: remove all @entity directives from your entities. Everything else stays the same.
Event Handler Migrationβ
This is the final step of the migration which consists of two parts:
- Moving from AssemblyScript to TypeScript
- Updating Subgraph syntax to HyperIndex syntax
AssemblyScript to TypeScriptβ
HyperIndex uses TypeScript instead of AssemblyScript. Since AssemblyScript is a subset of TypeScript, you can simply copy most of your code over without worrying about major syntax changes.
Subgraph to HyperIndexβ
The HyperIndex workflow is very similar to Subgraphs, but there are a few important differences to keep in mind:
- Replace
ENTITY.save()withcontext.ENTITY.set(VALUES) - Handlers need to be async
- Use
awaitwhen loading entities
As you start using HyperIndex, youβll pick up the differences quickly.
Here is a code snippet to give you a sense of what these changes look like in practice.
The Graph - eventHandler.ts
export function handleSubscription(event: SubscriptionEvent): void {
const subscription = new Subscribe(event.transaction.hash + event.logIndex);
subscription.tokenId = event.params.tokenId;
subscription.address = event.params.subscriber.toHexString();
subscription.logIndex = event.logIndex;
subscription.blockNumber = event.block.number;
subscription.position = event.params.tokenId;
subscription.save();
}
HyperIndex - eventHandler.ts
PoolManager.Subscription.handler( async (event, context) => {
const entity = {
id: event.transaction.hash + event.logIndex,
tokenId: event.params.tokenId,
address: event.params.subscriber,
blockNumber: event.block.number,
logIndex: event.logIndex,
position: event.params.tokenId
}
context.Subscription.set(entity);
})
For a few extra tips on migrating from Alchemy to Envio, check out our other migration guide in our docs.
Share Your Learningsβ
If you come across anything useful during your migration, please feel free to contribute. Simply open a PR to this guide and help future developers.
Getting Helpβ
Join our Discord if you need support. It is the fastest way to get direct help from the team and the community.
Migrate To V3β
File: migrate-to-v3.md
HyperIndex V3 is currently in alpha. While we don't plan major API changes, some features may still undergo minor breaking changes and developer experience improvements.
Migrate to HyperIndex V3 Alpha
15 full months have passed since the official HyperIndex v2.0.0. Since then, we have shipped 32 minor releases and multiple patches with zero breaking changes to the documented API. We also received PRs from 6 external contributors, grew from 1 GitHub star to over 470, and saw many big projects rely on HyperIndex.
HyperIndex V3 Alpha focuses on modernizing the codebase and laying the foundation for many more months of development. This guide walks you through upgrading from V2 to V3.
New Featuresβ
CommonJS β ESMβ
We migrated HyperIndex from CommonJS-only to ESM-only. This enables:
- Using the latest versions of libraries that have long since abandoned CommonJS support
- Top-level await in handler files
Top-Level Awaitβ
Thanks to the migration to ESM, you can now use await directly in handler and other files:
const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
// Load data before registering handlers
const addressesFromServer = await loadWhitelistedAddresses();
ERC20.Transfer.handler(
async ({ event, context }) => {
// ... your handler logic
},
{
wildcard: true,
eventFilters: [
{ from: ZERO_ADDRESS, to: addressesFromServer },
{ from: addressesFromServer, to: ZERO_ADDRESS },
],
}
);
Automatic Handler Registration (src/handlers)β
We introduced automatic registration of handler files located in src/handlers.
Previously, you needed to specify an explicit path to a handler file for every contract in config.yaml. Now you can remove all of the paths from config.yaml and simply move the files to src/handlers. You can name the files however you want, but we suggest using contract names and having a file per contract.
If you don't like src/handlers, use the handlers option in config.yaml to customize it.
The explicit handler field in config.yaml still works, so you don't need to change anything immediately.
RPC for Live Indexingβ
Built by an external contributor @cairoeth to allow specifying live mode for an RPC data source to embrace low-latency head tracking:
rpc:
- url: https://eth-mainnet.your-rpc-provider.com
for: live
In this case, the RPC won't be used for historical sync but will join the source selection logic when entering live indexing.
Chain State on Contextβ
The Handler Context object provides chain state via the chain property:
ERC20.Approval.handler(async ({ context }) => {
console.log(context.chain.id); // 1 - The chain id of the event
console.log(context.chain.isLive); // true - Whether the event chain is indexing at the head
});
Indexer State & Configβ
As a replacement for the deprecated and removed getGeneratedByChainId, we introduce the indexer value. It provides nicely typed chains and contract data from your config, as well as the current indexing state, such as isLive and addresses. Use indexer either at the top level of the file or directly from handlers. It returns the latest indexer state.
With this change, we also introduce new official types: Indexer, EvmChainId, FuelChainId, and SvmChainId.
indexer.name; // "uniswap-v4-indexer"
indexer.description; // "Uniswap v4 indexer"
indexer.chainIds; // [1, 42161, 10, 8453, 137, 56]
indexer.chains[1].id; // 1
indexer.chains[1].startBlock; // 0
indexer.chains[1].endBlock; // undefined
indexer.chains[1].isLive; // false
indexer.chains[1].PoolManager.name; // "PoolManager"
indexer.chains[1].PoolManager.abi; // unknown[]
indexer.chains[1].PoolManager.addresses; // ["0x000000000004444c5dc75cB358380D2e3dE08A90"]
Conditional Event Handlersβ
Now it's possible to return a boolean value from the eventFilters function to disable or enable the handler conditionally.
ERC20.Transfer.handler(
async ({ event, context }) => {
// ... your handler logic
},
{
wildcard: true,
eventFilters: ({ chainId }) => {
// Skip all ERC20 on Polygon
if (chainId === 137) {
return false;
}
// Track all ERC20 on Ethereum Mainnet
if (chainId === 1) {
return true;
}
// Track only whitelisted addresses on other chains
return [
{ from: ZERO_ADDRESS, to: WHITELISTED_ADDRESSES[chainId] },
{ from: WHITELISTED_ADDRESSES[chainId], to: ZERO_ADDRESS },
];
},
}
);
Automatic Contract Configurationβ
Started automatically configuring all globally defined contracts. This fixes an issue where addContract crashed because the contract was defined globally but not linked for a specific chain. Now it's done automatically:
contracts:
- name: UniswapV3Factory
events: # ...
- name: UniswapV3Pool
events: # ...
chains:
- id: 1
start_block: 0
contracts:
- name: UniswapV3Factory
address: 0x1F98431c8aD98523631AE4a59f267346ea31F984
# UniswapV3Pool no longer needed here - auto-configured from global contracts
- id: 10
start_block: 0
contracts:
- name: UniswapV3Factory
address: 0x1F98431c8aD98523631AE4a59f267346ea31F984
# UniswapV3Pool no longer needed here - auto-configured from global contracts
ClickHouse Sink (Experimental)β
We added experimental support for a ClickHouse Sink. Postgres still serves as the primary database, and you can additionally sink the entities to a ClickHouse database that is restart- and reorg-resistant.
Configure with environment variables: ENVIO_CLICKHOUSE_SINK_HOST, ENVIO_CLICKHOUSE_SINK_DATABASE, ENVIO_CLICKHOUSE_SINK_USERNAME, ENVIO_CLICKHOUSE_SINK_PASSWORD. Currently supported only on Dedicated Plan.
Do not run multiple Sinks to the same database at the same time.
HyperSync Source Improvementsβ
Multiple updates on the HyperSync side to achieve smaller latency and less traffic:
- Server-Sent Events instead of polling to get updates about new blocks
- CapnProto instead of JSON for query serialization
- Cache for queries with repetitive filters - huge egress saving when indexing thousands of addresses
Fuel Block Handler Supportβ
Block handlers are now supported for Fuel indexing.
Solana Support (Experimental)β
HyperIndex now supports Solana with RPC as a source. This feature is experimental and may undergo minor breaking changes.
To initialize a Solana project:
pnpx envio@3.0.0-alpha.7 init svm
See the Solana documentation for more details.
pnpx envio init Improvementsβ
- Removed language selection to prefer TypeScript by default
- Cleaned up templates to follow the latest good practices
- Added new templates to highlight HyperIndex features, starting with:
Feature: Factory Contract
Block Handler Only Indexersβ
Now it's possible to create indexers with only block handlers. Previously, it was required to have at least one event handler for it to work. The contracts field became optional in config.yaml.
Flexible Entity Fieldsβ
We no longer have restrictions on entity field names, such as type and others. Shape your entities any way you want. There are also improvements in generating database columns in the same order as they are defined in the schema.graphql.
Unordered Multichain Mode by Defaultβ
Unordered multichain mode is now the default behavior. This provides better performance for most use cases. If you need ordered multichain behavior, you can explicitly set multichain: ordered in your config.
Preload Optimization by Defaultβ
Preload optimization is now enabled by default, replacing the previous loaders and preload_handlers options. This improves historical sync performance automatically.
TUI Improvementsβ
We gave our TUI some love, making it look more beautiful and compact. It also consumes fewer resources, shares a link to the Hasura playground, and dynamically adjusts to the terminal width.
!TUI
New Testing Framework (Experimental)β
We introduced a new testing framework that allows you to test handlers' logic using real blockchain data and programmatically debug code without repetitive local runs. Key capabilities include:
- Testing block and event handlers together
- Snapshot testing support
- Parallel test execution via worker thread isolation
The framework integrates with Vitest, replacing the previous mocha/chai setup with a single package that doesn't require configuration by default and includes snapshot testing out-of-the-box.
describe("Indexer Testing", () => {
it("Should create accounts from ERC20 Transfer events", async () => {
const indexer = createTestIndexer();
expect(
await indexer.process({
chains: {
1: {
startBlock: 10_861_674,
endBlock: 10_861_674,
},
},
}),
"Should find the first mint at block 10_861_674"
).toMatchInlineSnapshot(`
{
"changes": [
{
"Account": {
"sets": [
{
"balance": -1000000000000000000000000000n,
"id": "0x0000000000000000000000000000000000000000",
},
{
"balance": 1000000000000000000000000000n,
"id": "0x41653c7d61609d856f29355e404f310ec4142cfb",
},
],
},
"block": 10861674,
"blockHash": "0x32e4dd857b5b7e756551a00271e44b61dbda0a91db951cf79a3e58adb28f5c09",
"chainId": 1,
"eventsProcessed": 1,
},
],
}
`);
});
});
See the Testing documentation for more details.
Podman Supportβ
Beyond Docker, HyperIndex now supports Podman for local development environments. This provides an alternative container runtime for developers who prefer Podman or have it available in their environment.
Nested Tuples for Contract Importβ
The envio init command now supports contracts with nested tuples in event signatures, which was previously a limitation when importing contracts.
PostgreSQL Update for Local Docker Composeβ
The local development Docker Compose setup now uses PostgreSQL 18.1 (upgraded from 17.5).
Breaking Changesβ
Node.js & Runtimeβ
- Node.js 22 is now the minimum required version, while 24 is the recommended version
- Changes in handler files don't trigger codegen on
pnpm dev
Handler API Changesβ
- Removed
experimental_createEffectin favor ofcreateEffect - Renamed transaction field
kindtotype - For block handlers:
block.chainIdis removed in favor ofcontext.chain.id Addresstype changed fromstringto`0x${string}`- Removed
transaction.chainIdfrom field selection β usecontext.chain.idorevent.chainIdinstead
config.yaml Changesβ
- Renamed
networkstochains - Renamed
confirmed_block_thresholdtomax_reorg_depth - Removed
unordered_multichain_modeflag, replaced withmultichain: ordered | unordered(default:unordered) - Removed
loadersoption (now always enabled via Preload Optimization) - Removed
preload_handlersoption (now always enabled) - Removed
preRegisterDynamicContractsoption