Skip to main content

Documentation Index

Fetch the complete documentation index at: https://beta.docs.sqd.dev/llms.txt

Use this file to discover all available pages before exploring further.

evmDecoder() bundles an EVM log query with a decoding transform into a single reusable module. Pass the result as an output to evmPortalStream:
import { commonAbis, evmDecoder, evmPortalStream } from '@subsquid/pipes/evm'

const stream = evmPortalStream({
  portal: 'https://portal.sqd.dev/datasets/ethereum-mainnet',
  outputs: {
    transfers: evmDecoder({
      range: { from: '0' },
      contracts: ['0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48'],
      events: { transfer: commonAbis.erc20.events.Transfer },
    }),
  },
})
evmDecoder() can:
  • Fetch from specific contracts — pass an array of addresses to contracts. Omit it entirely to receive matching events from every contract on-chain.
  • Filter by indexed parameters — instead of a bare event, supply { event, params } to select only logs where specific indexed arguments match.
  • Dynamically discover contracts via factories — pass a contractFactory() to contracts instead of a static list. See the Factory guide.
  • Handle decode errors with a custom onError callback instead of letting them propagate.
See the evmDecoder() reference for all parameters.

Specifying events

The events parameter maps output field names to event specifications. There are three ways to obtain an event specification.

commonAbis

commonAbis is a built-in collection of ABI modules for common token standards. Currently it ships one module, erc20:
import { commonAbis, evmDecoder } from '@subsquid/pipes/evm'

evmDecoder({
  range: { from: 'latest' },
  contracts: ['0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48'],
  events: {
    transfers: commonAbis.erc20.events.Transfer,
    approvals: commonAbis.erc20.events.Approval,
  },
})
See the commonAbis reference for the full list of available events and functions.

Typegen modules

@subsquid/evm-typegen generates TypeScript ABI modules from JSON ABIs. Each generated module exports typed events and functions objects, translating Solidity types to TypeScript — event argument types are statically known at compile time, so you get precise type checking and IDE autocompletion across the entire pipeline. Install the tool:
npm install -D @subsquid/evm-typegen
Generate a module from a local JSON ABI file:
npx squid-evm-typegen src/abi your-contract.json
This creates src/abi/your-contract.ts. The tool also accepts a contract address (requires specifying --chain-id) or an arbitrary URL. Use events from a generated module exactly as with commonAbis:
import * as usdcAbi from './abi/usdc'

evmDecoder({
  range: { from: 'latest' },
  contracts: ['0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48'],
  events: {
    transfers: usdcAbi.events.Transfer,
    approvals: usdcAbi.events.Approval,
  },
})

Raw JSON via defineAbi()

defineAbi() converts a JSON ABI array to a subsquid ABI module at runtime, with no code generation step. This is the quickest route — useful for one-off scripts or prototypes — but it comes at a cost: when the ABI is loaded from an external JSON file, event argument fields are typed as any, since TypeScript cannot inspect the runtime JSON value at compile time.
import { defineAbi, evmDecoder } from '@subsquid/pipes/evm'
import erc20Json from './erc20.json'

const erc20 = defineAbi(erc20Json) // event args are `any`

evmDecoder({
  range: { from: 'latest' },
  contracts: ['0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48'],
  events: { transfers: erc20.events.Transfer },
})
defineAbi() also accepts Hardhat and Foundry artifact objects — it reads the abi field automatically:
import artifact from './artifacts/MyContract.json'

const myContract = defineAbi(artifact) // reads artifact.abi
If you define the ABI inline with as const, TypeScript can infer the exact decoded types for scalar fields:
const erc20 = defineAbi([
  {
    type: 'event',
    name: 'Transfer',
    inputs: [
      { indexed: true,  name: 'from',  type: 'address' },
      { indexed: true,  name: 'to',    type: 'address' },
      { indexed: false, name: 'value', type: 'uint256' },
    ],
  },
] as const)

// erc20.events.Transfer.decode() returns { from: string, to: string, value: bigint }
For projects where full type safety matters end-to-end, prefer the typegen route instead.