Skip to content

Create a subgrove

This guide walks through creating a BlockchainIndexing subgrove: pointing Willow at a contract so its events become a live, queryable, verifiable dataset.

By the end you’ll understand the manifest (which contracts and events to index), the schema (the shape of the rows), and every field you can set.

  • A Willow account (free tier, no card) — sign up at dashboard.willow.tech.
  • The contract address, the events you want, and the block to start from.
  • A small amount of WILL to fund the indexers (set at registration).

Willow indexes events declaratively — you don’t write handler code for standard contracts. Two pieces work together:

  1. The manifest lists each contract and the event signatures to watch.
  2. The schema declares a GraphQL entity per event.

The rule that connects them: an entity’s type name must match the event name, and its fields map positionally to the event’s parameters. Willow decodes each matching log and writes one row, auto-filling metadata fields (id, blockNumber, timestamp, transactionHash). No handler function is involved.

The manifest is JSON. Here is a complete, valid example — USDC Transfer events on Ethereum mainnet:

{
"spec_version": "1.0.0",
"description": "USDC transfers on Ethereum mainnet",
"data_sources": [
{
"name": "USDC",
"network": "mainnet",
"address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"abi": "ERC20",
"start_block": 6082465,
"events": [
"Transfer(address indexed,address indexed,uint256)"
]
}
]
}

The schema is a separate field you provide at registration (it is not inside the manifest). Declare one @entity type per event, named after the event:

type Transfer @entity {
id: ID!
from: String!
to: String!
value: BigInt!
blockNumber: BigInt!
timestamp: BigInt!
transactionHash: String!
}

How the fields map:

  • type Transfer matches the Transfer(...) event.
  • from, to, value are your data fields — they map, in order, to the event’s three parameters (address, address, uint256).
  • id, blockNumber, timestamp, transactionHash are metadata — Willow fills these automatically. (id is {txHash}-{logIndex}.)

So the order of your non-metadata fields must match the order of the event parameters.

TypeUse for
Stringtext, addresses as hex, anything textual
BigInt256-bit integers (token amounts, prices) — stored exactly
Int32-bit signed integers
Booleantrue/false
Byteshex byte strings
Address20-byte addresses
BigDecimalarbitrary-precision decimals
Timestampblock timestamps

Each entry in events is a Solidity event signature, types only (no parameter names), with an optional indexed keyword per parameter:

Transfer(address indexed,address indexed,uint256)
Supply(address indexed,address,address indexed,uint256,uint16 indexed)
  • Use indexed to mark parameters declared indexed in the contract (they’re read from log topics; non-indexed come from the data blob). Solidity allows at most 3 indexed parameters.
  • Up to 32 events per data source.
FieldTypeRequiredNotes
spec_versionstringyesMust equal "1.0.0".
descriptionstringno≤ 1024 chars.
data_sourcesarrayyes1–64 data sources.
deferred_completenessboolnoDefaults to false.
FieldTypeNotes
namestringLabel; alphanumeric / - / _, ≤ 64 chars.
networkstringCanonical chain id (see below).
addressstring0x + 40 hex.
abistringA label only (e.g. ERC20) — the real decode info is the event signatures. ≤ 64 chars.
start_blocknumberBlock to begin indexing from.
eventsarray1–32 event signatures.
FieldTypeDefaultNotes
min_indexersnumber11–10.
max_indexersnumber31–10, ≥ min_indexers.
reward_per_epochstring0.1 WILLPer indexer, per epoch, in the smallest WILL unit (1 WILL = 10¹⁸). Max 1000 WILL.
epoch_lengthnumber100Epoch length in blocks.
min_indexer_stakestring100,000 WILLPer-indexer stake, smallest WILL unit.

execution_mode chooses how the indexing is verified. Defaults to ConsensusExecution. See Execution modes for all variants and their sub-config.

network must be one of these exact canonical ids (no aliases):

mainnet, sepolia, holesky, bsc, optimism, arbitrum-one, base, polygon, solana-mainnet.

You register by submitting a RegisterSubgrove transaction. It carries:

  • subgrove_id — your unique id.
  • schema — the GraphQL schema string above.
  • the BlockchainIndexing mode — manifest_content (the manifest JSON), execution_mode, indexer_config (and optional wasm_modules).
  • initial funding (WILL).

Go to Subgroves → Register a subgrove, keep Mode on BlockchainIndexing, fill in the Subgrove ID, funding, and the Config, then Register.

Any of the SDKs can sign and submit the transaction — useful for scripting or CI. See the SDK reference for the exact register call.

  • Watch indexing progress and validators in the dashboard.
  • Query the dataset — see Query indexed data.
  • Every row you read back is Willow verified.