packages/cli/templates/static/shared/.claude/skills/indexing-factory/SKILL.md
Use when indexing contracts deployed by factory contracts at runtime. contractRegister API, dynamic contract config (no address), async registration, and same-block event coverage.
npx skillsauth add enviodev/hyperindex indexing-factoryInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
For contracts created at runtime by factory contracts (e.g., Uniswap Pair creation).
Dynamic contracts have no address — they're registered by contractRegister:
contracts:
- name: Factory
events:
- event: PairCreated(indexed address token0, indexed address token1, address pair, uint256)
- name: Pair
# No address — registered dynamically
events:
- event: Swap(indexed address sender, uint256 amount0In, ...)
- event: Sync(uint112 reserve0, uint112 reserve1)
chains:
- id: 1
contracts:
- name: Factory
address:
- 0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f
- name: Pair
# No address here — will be registered by contractRegister
Must be defined BEFORE the handler. Registers new contract addresses for indexing:
Factory.PairCreated.contractRegister(({ event, context }) => {
context.addPair(event.params.pair);
});
Factory.PairCreated.handler(async ({ event, context }) => {
const pair: Pair = {
id: `${event.chainId}-${event.params.pair}`,
token0_id: `${event.chainId}-${event.params.token0}`,
token1_id: `${event.chainId}-${event.params.token1}`,
};
context.Pair.set(pair);
});
The context.add<ContractName>() methods are auto-generated based on contracts in config that have no address.
Perform external calls to decide which contract to register:
NftFactory.SimpleNftCreated.contractRegister(async ({ event, context }) => {
const version = await getContractVersion(event.params.contractAddress);
if (version === "v2") {
context.addSimpleNftV2(event.params.contractAddress);
} else {
context.addSimpleNft(event.params.contractAddress);
}
});
When a dynamic contract is registered, HyperIndex indexes all events from that contract in the same block where it was created — even events from earlier transactions in that block.
Full reference: https://docs.envio.dev/docs/HyperIndex-LLM/hyperindex-complete
development
Write and run tests for HyperIndex indexers using Vitest and createTestIndexer(). Covers test setup, processing block ranges, asserting entity changes with toMatchInlineSnapshot, and TDD workflow. Use when writing tests, debugging handler output, or verifying indexer behavior.
data-ai
Migrate a TheGraph subgraph to Envio HyperIndex using TDD. Covers schema conversion (remove @entity, Bytes->String, @derivedFrom), handler translation (save->set, store.get->context.get, templates->contractRegister), and verification against subgraph data.
data-ai
Use when indexing all instances of a contract across all addresses (e.g., all ERC-20 transfers on a chain). Config setup (no address), wildcard handler option, and event.srcAddress.
data-ai
Use when needing transaction-level data in handlers. Configure field_selection to include transaction fields on events, and access via event.transaction. No native transaction handler — access through event handlers.