
Subsquid
- 6 installs
- 4 repo stars
- Updated February 25, 2026
- hairyf/blockchain-master
Build batch-based blockchain indexers with Subsquid (Squid SDK) - EVM/Substrate processors, typegen decoding, and a GraphQL API.
About
Subsquid provides the SQD Network historical-data API and a TypeScript Squid SDK for building batch indexers with EVM or Substrate processors and stores. A developer uses it to index on-chain data and serve it over GraphQL.
- Batch processors for EVM and Substrate with typegen decoding
- Postgres/file/BigQuery stores and optional GraphQL serving
Subsquid by the numbers
- 6 all-time installs (skills.sh)
- Ranked #334 of 479 Web3 & Blockchain skills by installs in the Skillselion catalog
- Data as of Jul 13, 2026 (Skillselion catalog sync)
npx skills add https://github.com/hairyf/blockchain-master --skill subsquidAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 6 |
|---|---|
| repo stars | ★ 4 |
| Last updated | February 25, 2026 |
| Repository | hairyf/blockchain-master ↗ |
What it does
Build batch-based blockchain indexers with Subsquid (Squid SDK) - EVM/Substrate processors, typegen decoding, and a GraphQL API.
Files
Skill based on Subsquid docs, generated 2026-02-09. Official docs: https://docs.subsquid.io
Subsquid provides SQD Network (historical blockchain data API) and Squid SDK — a TypeScript toolkit for building batch-based indexers (squids). Squids use processors (EVM or Substrate), stores (Postgres, file, BigQuery), optional typegen for decoding, and optional GraphQL serving.
Core References
| Topic | Description | Reference |
|---|---|---|
| Overview | Squid SDK architecture — processor, store, typegen, GraphQL; SQD Network | core-overview |
| EVM Processor | EvmBatchProcessor — gateway, RPC, addLog, setFields, batch context | core-evm-processor |
| Schema & TypeORM | schema.graphql, typeorm-codegen, TypeormDatabase, store API | core-schema-typeorm |
Features
| Topic | Description | Reference |
|---|---|---|
| EVM Typegen | squid-evm-typegen — ABI → decoding and state-query facades | features-evm-typegen |
| CLI | sqd init, run, deploy; templates and project layout | features-cli |
| GraphQL | OpenReader — schema-based GraphQL API from Postgres | features-graphql |
Best Practices
| Topic | Description | Reference |
|---|---|---|
| Batch Processing | In-memory aggregation, batch writes, avoid per-item DB ops | best-practices-batch-processing |
External Links
Generation Info
- Source:
sources/subsquid(https://github.com/subsquid/docs) - Git SHA:
c2bf613f5bbf396d02acf825d8818e31c1d74837 - Generated: 2026-02-09
- Docs used: overview.mdx, sdk/overview.mdx, sdk/quickstart.md, sdk/reference (processors, schema-file, store, openreader-server), sdk/resources (batch-processing, typegen), squid-cli (init, run)
Batch Processing Best Practices
Squid SDK processes data in batches. The handler receives ctx.blocks; it should minimize DB round-trips by aggregating in memory and writing once per batch.
Do: aggregate then batch write
1. Decode and normalize items from ctx.blocks into an in-memory structure (e.g. array or map keyed by entity id). 2. If you need existing entities, batch-load by ID set: ctx.store.findBy(Entity, { id: In([...ids]) }), put in a Map. 3. Apply business logic in memory (create/update map entries). 4. Single write at the end: await ctx.store.upsert([...map.values()]) or ctx.store.insert(entities).
processor.run(db, async (ctx) => {
const gravatars = new Map<string, Gravatar>()
for (const block of ctx.blocks) {
for (const log of block.logs) {
if (/* not relevant */) continue
const data = extractData(log)
gravatars.set(data.id, new Gravatar(data))
}
}
await ctx.store.upsert([...gravatars.values()])
})Don’t: per-item DB writes in the loop
Avoid await ctx.store.save(entity) or upsert inside the inner loop. It drastically reduces throughput. Use an in-memory cache (e.g. Map) and one batch save per batch.
EVM state queries
When using direct RPC state calls, batch them: use the generated Multicall facade (--multicall with squid-evm-typegen) or batch eth_call requests instead of one call per item.
Migrating from handler-based code
When moving from subgraph-style handlers, you can keep per-item handler functions and call them from a loop over ctx.blocks/logs/transactions as an intermediate step; then refactor to the in-memory aggregate + single batch write pattern for better performance.
<!-- Source references:
- https://docs.subsquid.io/sdk/resources/batch-processing
-->
EvmBatchProcessor
EvmBatchProcessor from @subsquid/evm-processor indexes EVM chains. Configure data sources and requested data, then run with a store and a batch handler.
Data sources (required: at least one)
- `setGateway(url | GatewaySettings)` — SQD Network gateway (historical, fast). Use when the network has a gateway.
- `setRpcEndpoint(rpc: string | ChainRpc)` — Chain RPC. Used for real-time ingestion (unfinalized blocks), direct RPC queries in code, or when there is no gateway.
ChainRpccan specifyurl,capacity,maxBatchCallSize,rateLimit,requestTimeout,headers.
Choose based on use case:
- Real-time + gateway available: set both
setGateway()andsetRpcEndpoint(); processor uses gateway for history then RPC for hot blocks. - Only historical, no RPC:
setGateway()only. - No gateway (e.g. local node):
setRpcEndpoint()only. - Direct RPC queries in code:
setRpcEndpoint()required; addsetGateway()to reduce RPC load; optionally disable RPC ingestion withsetRpcDataIngestionSettings({ disabled: true }).
`setFinalityConfirmation(nBlocks: number)` — Required when RPC ingestion is enabled. Number of blocks after which data is considered final (e.g. 75 for Ethereum mainnet).
Data requests
- `addLog(options)` — Event logs.
options:address?,topic0–topic3?,range?; related:transaction?,transactionLogs?,transactionTraces?. - `addTransaction(options)` — Transactions (filter by address, sighash, range).
- `addTrace()` / `addStateDiff()` — Traces and state diffs (EVM).
`setFields(fields)` — Select which fields to fetch for logs, transactions, traces, state diffs, block headers. Omit to use defaults.
`setBlockRange({ from, to? })` — Global block range; processor exits with 0 when upper bound is reached.
Batch handler and context
processor.run(db, async (ctx) => {
for (const block of ctx.blocks) {
// block.header, block.logs, block.transactions, block.traces, block.stateDiffs
for (const log of block.logs) {
// decode and collect
}
}
await ctx.store.insert(entities) // batch write
})ctx.blocks is an array of BlockData: header, logs, transactions, traces, stateDiffs. Field availability follows setFields(). Use typegen-generated event topics/sighashes for filtering (e.g. usdcAbi.events.Transfer.topic).
Other settings
- `setRpcDataIngestionSetting(settings)` — RPC ingestion:
disabled,preferTraceApi,useDebugApiForStateDiffs,debugTraceTimeout,headPollInterval,newHeadTimeout. - `includeAllBlocks(range?)` — Fetch all blocks in range, not only blocks with requested items.
- `setPrometheusPort(port)` — Metrics server port.
<!-- Source references:
- https://docs.subsquid.io/sdk/reference/processors/evm-batch/general
- https://docs.subsquid.io/sdk/reference/processors/evm-batch/logs
- https://docs.subsquid.io/sdk/reference/processors/evm-batch/context-interfaces
-->
Subsquid / Squid SDK Overview
Subsquid provides SQD Network (historical blockchain data API) and Squid SDK (TypeScript toolkit for building indexers). A squid is an indexing project that retrieves data from SQD Network (or RPC), transforms it in batches, and persists to a store (Postgres, files, BigQuery). All processing is batch-based: the handler receives ctx.blocks and should minimize per-item DB hits.
Required components
- Processor — Main process and main object;
processor.run(store, handler)is the entry point. Handles data retrieval and transformation. EvmBatchProcessor(@subsquid/evm-processor) for EVM chains.SubstrateBatchProcessor(@subsquid/substrate-processor) for Substrate-based chains.- Store — Where processors persist data. Options:
TypeormDatabase(@subsquid/typeorm-store+@subsquid/typeorm-codegen+@subsquid/typeorm-migration) → PostgreSQL.- File store (
@subsquid/file-store) → local/S3 files (CSV, JSON, Parquet). - BigQuery store (
@subsquid/bigquery-store).
Any processor can be used with any store.
Optional components
- Typegen — Generates decoding/utility code from ABIs or metadata:
squid-evm-typegen,squid-substrate-typegen,squid-ink-typegen. Install with--save-dev. - GraphQL server — For Postgres squids, data can be served via GraphQL (e.g. OpenReader
@subsquid/graphql-serveror other options; see Serving GraphQL). - Squid CLI —
sqdfor init, run, deploy (templates, run processor + API, SQD Cloud).
Data flow
1. Configure processor: set gateway (SQD Network URL) and/or RPC endpoint, finality, add data requests (e.g. addLog(), addTransaction()). 2. processor.run(db, async (ctx) => { ... }): handler receives batches of blocks; each block has logs, transactions, traces, stateDiffs (EVM). 3. Decode and transform in memory; batch upsert/insert via ctx.store. 4. Optionally run GraphQL server against the same DB.
When to use
- Custom APIs from smart contract or chain data.
- Low-cost, performant data pipelines (batch ETL).
- Real-time indexing (<1s chain latency) when using RPC for hot blocks and gateway for history.
<!-- Source references:
- https://docs.subsquid.io/overview
- https://docs.subsquid.io/sdk/overview
-->
Schema and TypeORM Store
Squids that persist to Postgres use a schema file (schema.graphql), TypeORM codegen, and TypeormDatabase. The schema models entities and relations; codegen produces TypeORM entities; the store exposes insert/upsert/find APIs inside the batch handler.
Schema file
schema.graphql uses a GraphQL dialect (loosely compatible with subgraph schema). Defines entities with @entity, fields (e.g. ID!, String, BigInt!), and relations. Used to:
- Generate TypeORM entities.
- Drive DB migrations.
- Optionally serve GraphQL API.
TypeORM codegen
npx squid-typeorm-codegenReads schema.graphql and generates TypeORM entity classes (default output: src/model/generated). Generate after schema changes, then run migrations.
TypeormDatabase and store
const db = new TypeormDatabase({ supportHotBlocks: true })
processor.run(db, async (ctx) => {
// ctx.store implements Store interface
})Constructor options: stateSchema, isolationLevel, supportHotBlocks (default true for fork handling), projectDir.
Batch write: Prefer batch operations in the handler.
- `ctx.store.insert(e | e[])` — Insert; fails on duplicate.
- `ctx.store.upsert(e | e[])` — Upsert; does not cascade to relations.
- `ctx.store.remove(e | E[], id?)` — Delete by entity or by ID(s).
Read: Same as TypeORM EntityManager: get, find, findBy, findOne, findOneBy, findOneOrFail, findOneByOrFail, count, countBy. Use In(), LessThan, Like, etc. from TypeORM for filters. Use relations in find options to load relations.
Connection: env vars DB_HOST, DB_PORT, DB_NAME, DB_USER, DB_PASS, DB_SSL, etc., or single DB_URL.
<!-- Source references:
- https://docs.subsquid.io/sdk/reference/schema-file/intro
- https://docs.subsquid.io/sdk/reference/store/typeorm
-->
Squid CLI (sqd)
Squid CLI (@subsquid/cli, global: npm i -g @subsquid/cli) scaffolds and runs squids locally and deploys to SQD Cloud.
Init project
sqd init NAME [-t TEMPLATE] [--dir DIR] [-r]- NAME — Project name (alphanumeric or dash).
- -t, --template — GitHub repo URL with valid
squid.yamlin root, or alias: evm— Minimal EVM squid.abi— Generate squid from contract ABI (events + txs).multichain— Multi-chain indexing.gravatar— Sample Gravatar EVM squid.substrate,ink,ink-abi,frontier-evm— Substrate/Ink/Frontier EVM.- -d, --dir — Target directory (default: new folder NAME).
- -r, --remove — Clean target dir if it exists.
Example: sqd init my-squid -t https://github.com/subsquid-labs/showcase01-all-usdc-transfers
Run and deploy
- `sqd run` — Run all processes defined in the squid (e.g. processor + GraphQL server) according to project config.
- `sqd deploy` — Deploy to SQD Cloud (auth and manifest required).
Other commands: sqd logs, sqd secrets, sqd prod, etc. See project squid.yaml and Squid CLI reference for full command set.
<!-- Source references:
- https://docs.subsquid.io/squid-cli/init
- https://docs.subsquid.io/squid-cli/run
- https://docs.subsquid.io/squid-cli/installation
-->
EVM Typegen (squid-evm-typegen)
squid-evm-typegen generates TypeScript facades for decoding EVM logs/transactions and for eth_call-style state queries. Use in squids that index EVM data.
Input: ABI
- Local JSON:
npx squid-evm-typegen src/abi abi/erc20.jsonor./abi/*.json. - Etherscan (API key):
npx squid-evm-typegen --etherscan-api-key <key> src/abi 0xContractAddress. - URL:
npx squid-evm-typegen src/abi https://example.com/abi.json.
Use fragment suffix to set output basename: 0xAddress#my-contract-name. Add --multicall to generate Multicall facade for batched state calls. Generated code depends on @subsquid/evm-abi.
Output and usage
Generated modules expose:
- Event decoding — e.g.
usdcAbi.events.Transfer.topic,usdcAbi.events.Transfer.decode(log). - Function sighashes and call decoding — for transactions and direct RPC calls.
- State query helpers — for
eth_callbatched via Multicall when using--multicall.
In the batch handler, filter by topic then decode:
if (log.topics[0] === usdcAbi.events.Transfer.topic) {
const { from, to, value } = usdcAbi.events.Transfer.decode(log)
}Use state queries when you need contract state at a block; batch them (e.g. via generated Multicall) instead of many single RPC calls.
<!-- Source references:
- https://docs.subsquid.io/sdk/resources/tools/typegen/generation
- https://docs.subsquid.io/sdk/resources/tools/typegen/state-queries
- https://docs.subsquid.io/sdk/resources/tools/typegen/decoding
-->
Serving GraphQL (OpenReader)
Postgres-backed squids can expose data via a GraphQL API. OpenReader (@subsquid/graphql-server) builds an API from the same schema.graphql used for TypeORM codegen.
Run server
npx squid-graphql-serverListens on GQL_PORT (default 4350). DB connection uses DB_* env vars. In SQD Cloud, typically run as api: service in the deployment manifest.
API shape
- `squidStatus { height }` — Last processed block.
- `{entityName}ById(id)` — Get entity by ID.
- `{entityName}ByUniqueInput(...)` — Get by unique field(s).
- `{entityName}sConnection(...)` — List with filters, AND/OR, nested/cross-relation fields, Relay-style cursor pagination.
Custom scalars: DateTime (ISO), Bytes (hex with 0x), BigInt (string).
OpenReader is one option; the docs recommend checking Serving GraphQL for current alternatives (OpenReader has limitations around subscriptions and Apollo v3).
<!-- Source references:
- https://docs.subsquid.io/sdk/reference/openreader-server/overview
- https://docs.subsquid.io/sdk/resources/serving-graphql
-->