Use this file to discover all available pages before exploring further.
Use the factory pattern when you need to index events from contracts that are deployed dynamically by a known factory contract — for example, Uniswap V3 pools created by the UniswapV3Factory.
The examples below use typegen-generated ABI modules. See Specifying events for how to generate them from a JSON ABI.
Track events from contracts created by a factory. The factory() helper discovers child contracts from the factory’s creation events and maintains the address list in a local SQLite database.
import { evmPortalStream, evmDecoder, factory, factorySqliteDatabase } from "@subsquid/pipes/evm";import { createTarget } from "@subsquid/pipes";import * as factoryAbi from "./abi/uniswap-v3-factory";import * as poolAbi from "./abi/uniswap-v3-pool";await evmPortalStream({ portal: "https://portal.sqd.dev/datasets/ethereum-mainnet", outputs: evmDecoder({ range: { from: 12369621 }, contracts: factory({ address: "0x1f98431c8ad98523631ae4a59f267346ea31f984", event: factoryAbi.events.PoolCreated, parameter: "pool", database: factorySqliteDatabase({ path: "./uniswap-v3-pools.sqlite" }), }), events: { swap: poolAbi.events.Swap }, }),}).pipeTo(createTarget({ write: async ({ logger, read }) => { for await (const { data } of read()) { logger.info(`Parsed ${data.swap.length} swaps`); } },}));
To narrow which child contracts are tracked, pass an event object with a params field. Only creation events matching the specified parameter values are stored — unmatched contracts are ignored at both the portal and the local database level.
DecodedEvent<T, F> carries a .factory field with the creation event. Use it when you need to include factory context (e.g. pool token addresses) alongside each decoded event.
Show Full example: access factory event metadata
import { evmPortalStream, evmDecoder, factory, DecodedEvent, factorySqliteDatabase,} from "@subsquid/pipes/evm";import { createTarget } from "@subsquid/pipes";import * as factoryAbi from "./abi/uniswap-v3-factory";import * as poolAbi from "./abi/uniswap-v3-pool";function addFactoryMetadata<T, F>(event: DecodedEvent<T, F>) { return { ...event.event, blockNumber: event.block.number, factoryEvent: event.factory?.event, };}const decoder = evmDecoder({ range: { from: 12369621 }, contracts: factory({ address: "0x1f98431c8ad98523631ae4a59f267346ea31f984", event: factoryAbi.events.PoolCreated, parameter: "pool", database: factorySqliteDatabase({ path: "./uniswap-v3-pools.sqlite" }), }), events: { swap: poolAbi.events.Swap, mint: poolAbi.events.Mint },}).pipe(({ swap, mint }) => ({ swap: swap.map(addFactoryMetadata), mint: mint.map(addFactoryMetadata),}));await evmPortalStream({ portal: "https://portal.sqd.dev/datasets/ethereum-mainnet", outputs: decoder,}).pipeTo(createTarget({ write: async ({ logger, read }) => { for await (const { data } of read()) { for (const s of data.swap) { logger.info({ pool: s.factoryEvent?.pool, token0: s.factoryEvent?.token0, token1: s.factoryEvent?.token1, amount0: s.amount0.toString(), amount1: s.amount1.toString(), }); } } },}));