> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/graphprotocol/graph-node/llms.txt
> Use this file to discover all available pages before exploring further.

# Mapping Configuration

> Complete guide to configuring mappings, handlers, and event processing

## Overview

Mappings define the transformation logic that converts blockchain data into entities that can be queried through your subgraph's GraphQL API. Each mapping specifies:

* Which events, calls, or blocks to handle
* Which entities are affected
* Which ABIs are needed
* The AssemblyScript code that processes the data

## Mapping Fields

<ParamField path="kind" type="String" required>
  Must be `ethereum/events` for Ethereum event mappings.

  <Expandable title="Example">
    ```yaml theme={null}
    kind: ethereum/events
    ```
  </Expandable>
</ParamField>

<ParamField path="apiVersion" type="String" required>
  Semver string of the version of the Mappings API that will be used by the mapping script.

  Current recommended version: `0.0.7`

  <Expandable title="Example">
    ```yaml theme={null}
    apiVersion: 0.0.7
    ```
  </Expandable>
</ParamField>

<ParamField path="language" type="String" required>
  The language of the runtime for the Mapping API.

  **Possible values:**

  * `wasm/assemblyscript` - AssemblyScript compiled to WebAssembly

  <Expandable title="Example">
    ```yaml theme={null}
    language: wasm/assemblyscript
    ```
  </Expandable>
</ParamField>

<ParamField path="entities" type="Array<String>" required>
  A list of entities that will be ingested as part of this mapping.

  Must correspond to entity names defined in your GraphQL schema.

  <Expandable title="Example">
    ```yaml theme={null}
    entities:
      - User
      - Transaction
      - Token
    ```
  </Expandable>
</ParamField>

<ParamField path="abis" type="Array<ABI>" required>
  ABIs for the contract classes that should be generated in the mapping.

  Each ABI entry has a `name` and `file` field.

  <Expandable title="Example">
    ```yaml theme={null}
    abis:
      - name: ERC20
        file: ./abis/ERC20.json
      - name: Factory
        file: ./abis/Factory.json
    ```
  </Expandable>
</ParamField>

<ParamField path="eventHandlers" type="Array<EventHandler>">
  Handlers for specific events, which will be defined in the mapping script.

  See [Event Handlers](#event-handlers) for details.
</ParamField>

<ParamField path="callHandlers" type="Array<CallHandler>">
  A list of functions that will trigger a handler and the name of the corresponding handlers in the mapping.

  See [Call Handlers](#call-handlers) for details.
</ParamField>

<ParamField path="blockHandlers" type="Array<BlockHandler>">
  Defines block filters and handlers to process matching blocks.

  See [Block Handlers](#block-handlers) for details.
</ParamField>

<ParamField path="file" type="Path" required>
  The path of the mapping script (AssemblyScript file).

  <Expandable title="Example">
    ```yaml theme={null}
    file: ./src/mapping.ts
    ```
  </Expandable>
</ParamField>

<Warning>
  Each mapping is required to supply **at least one** handler type: `eventHandlers`, `callHandlers`, or `blockHandlers`.
</Warning>

## Event Handlers

Event handlers are triggered when specific events are emitted by the smart contract. This is the most common type of handler.

<ParamField path="event" type="String" required>
  An identifier for an event that will be handled in the mapping script.

  For Ethereum contracts, this must be the **full event signature** to distinguish from events that may share the same name.

  **Important:**

  * No alias types can be used
  * `uint` will not work, `uint256` must be used
  * Use indexed parameters as shown in the ABI

  <Expandable title="Example">
    ```yaml theme={null}
    event: Transfer(indexed address,indexed address,uint256)
    ```
  </Expandable>
</ParamField>

<ParamField path="handler" type="String" required>
  The name of an exported function in the mapping script that should handle the specified event.

  This function must be exported from your mapping file.

  <Expandable title="Example">
    ```yaml theme={null}
    handler: handleTransfer
    ```
  </Expandable>
</ParamField>

<ParamField path="topic0" type="String">
  A `0x` prefixed hex string.

  If provided, events whose topic0 is equal to this value will be processed by the given handler. When topic0 is provided, *only* the topic0 value will be matched, and not the hash of the event signature.

  This is useful for processing **anonymous events** in Solidity, which can have their topic0 set to anything.

  By default, topic0 is equal to the hash of the event signature.

  <Expandable title="Example">
    ```yaml theme={null}
    topic0: "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
    ```
  </Expandable>
</ParamField>

<ParamField path="receipt" type="Boolean">
  Set to `true` to receive the transaction receipt in the handler.

  When enabled, the handler will have access to receipt data including logs, gas used, and status.

  <Expandable title="Example">
    ```yaml theme={null}
    receipt: true
    ```
  </Expandable>
</ParamField>

### Event Handler Example

<Tabs>
  <Tab title="Manifest">
    ```yaml theme={null}
    eventHandlers:
      - event: Transfer(indexed address,indexed address,uint256)
        handler: handleTransfer
      - event: Approval(indexed address,indexed address,uint256)
        handler: handleApproval
    ```
  </Tab>

  <Tab title="Mapping Code">
    ```typescript theme={null}
    import { Transfer, Approval } from '../generated/Contract/ERC20'
    import { User, Transaction } from '../generated/schema'

    export function handleTransfer(event: Transfer): void {
      // Load or create sender
      let sender = User.load(event.params.from.toHex())
      if (sender == null) {
        sender = new User(event.params.from.toHex())
        sender.balance = BigInt.fromI32(0)
      }
      
      // Load or create receiver
      let receiver = User.load(event.params.to.toHex())
      if (receiver == null) {
        receiver = new User(event.params.to.toHex())
        receiver.balance = BigInt.fromI32(0)
      }
      
      // Update balances
      sender.balance = sender.balance.minus(event.params.value)
      receiver.balance = receiver.balance.plus(event.params.value)
      
      // Create transaction record
      let transaction = new Transaction(event.transaction.hash.toHex())
      transaction.from = sender.id
      transaction.to = receiver.id
      transaction.value = event.params.value
      transaction.timestamp = event.block.timestamp
      
      // Save entities
      sender.save()
      receiver.save()
      transaction.save()
    }

    export function handleApproval(event: Approval): void {
      // Handle approval event
    }
    ```
  </Tab>
</Tabs>

## Call Handlers

Call handlers are triggered when specific functions are called on the smart contract. Useful for tracking state changes that don't emit events.

<Warning>
  Call handlers require the transaction to be successful. Failed transactions do not trigger call handlers.
</Warning>

<ParamField path="function" type="String" required>
  An identifier for a function that will be handled in the mapping script.

  For Ethereum contracts, this is the **normalized function signature** to filter calls by.

  <Expandable title="Example">
    ```yaml theme={null}
    function: swap(uint256,uint256,address,bytes)
    ```
  </Expandable>
</ParamField>

<ParamField path="handler" type="String" required>
  The name of an exported function in the mapping script that should handle the specified call.

  <Expandable title="Example">
    ```yaml theme={null}
    handler: handleSwap
    ```
  </Expandable>
</ParamField>

### Call Handler Example

<Tabs>
  <Tab title="Manifest">
    ```yaml theme={null}
    callHandlers:
      - function: swap(uint256,uint256,address,bytes)
        handler: handleSwap
      - function: mint(address)
        handler: handleMint
    ```
  </Tab>

  <Tab title="Mapping Code">
    ```typescript theme={null}
    import { SwapCall, MintCall } from '../generated/Contract/UniswapV2Pair'
    import { Swap, Pair } from '../generated/schema'

    export function handleSwap(call: SwapCall): void {
      let pair = Pair.load(call.to.toHex())
      if (pair == null) return
      
      let swap = new Swap(call.transaction.hash.toHex())
      swap.pair = pair.id
      swap.amount0In = call.inputs.amount0Out
      swap.amount1In = call.inputs.amount1Out
      swap.to = call.inputs.to
      swap.timestamp = call.block.timestamp
      swap.save()
    }

    export function handleMint(call: MintCall): void {
      // Handle mint call
    }
    ```
  </Tab>
</Tabs>

## Block Handlers

Block handlers are triggered for every block (or blocks matching a filter). Useful for tracking time-based state changes or aggregate statistics.

<Warning>
  Block handlers can significantly impact indexing performance. Use filters to limit when they execute.
</Warning>

<ParamField path="handler" type="String" required>
  The name of an exported function in the mapping script that should handle the block.

  <Expandable title="Example">
    ```yaml theme={null}
    handler: handleBlock
    ```
  </Expandable>
</ParamField>

<ParamField path="filter" type="BlockHandlerFilter">
  Definition of the filter to apply. If none is supplied, the handler will be called on every block.

  See [Block Handler Filters](#block-handler-filters) for details.
</ParamField>

### Block Handler Filters

<ParamField path="kind" type="String" required>
  The selected block handler filter.

  **Possible values:**

  * `call` - Only run the handler if the block contains at least one call to the data source contract

  <Expandable title="Example">
    ```yaml theme={null}
    filter:
      kind: call
    ```
  </Expandable>
</ParamField>

### Block Handler Example

<Tabs>
  <Tab title="Manifest">
    ```yaml theme={null}
    blockHandlers:
      - handler: handleBlock
        filter:
          kind: call
    ```
  </Tab>

  <Tab title="Mapping Code">
    ```typescript theme={null}
    import { ethereum } from '@graphprotocol/graph-ts'
    import { Statistics } from '../generated/schema'

    export function handleBlock(block: ethereum.Block): void {
      let stats = Statistics.load('global')
      if (stats == null) {
        stats = new Statistics('global')
        stats.blockCount = 0
      }
      
      stats.blockCount = stats.blockCount + 1
      stats.lastBlockNumber = block.number
      stats.lastBlockTimestamp = block.timestamp
      stats.save()
    }
    ```
  </Tab>
</Tabs>

## Pre-declared Calls

Available from spec version **1.2.0**. Struct field access available from spec version **1.4.0**.

Declared calls are performed in parallel before the handler is run and can greatly speed up syncing. Mappings access the call results simply by using `ethereum.call` from the mappings.

<ParamField path="label" type="String" required>
  A label for the call for error messages and identification.

  <Expandable title="Example">
    ```yaml theme={null}
    label: getReserves
    ```
  </Expandable>
</ParamField>

<ParamField path="call" type="String" required>
  The call specification in the format: `<ABI>[<address>].<function>(<args>)`

  **Components:**

  * `ABI` - The name of an ABI from the `abis` section
  * `address` - An expression resolving to the contract address
  * `function` - The name of a view function in the contract
  * `args` - Expressions for the function arguments

  <Expandable title="Example">
    ```yaml theme={null}
    call: Pair[event.address].getReserves()
    ```
  </Expandable>
</ParamField>

### Expression Types

The expressions in pre-declared calls can be:

| Expression                        | Description                                                         |
| --------------------------------- | ------------------------------------------------------------------- |
| `event.address`                   | The address of the contract that emitted the event                  |
| `event.params.<name>`             | A simple parameter from the event                                   |
| `event.params.<name>.<index>`     | A field from a struct parameter by numeric index                    |
| `event.params.<name>.<fieldName>` | A field from a struct parameter by field name (spec version 1.4.0+) |

### Pre-declared Calls Example

<Tabs>
  <Tab title="Manifest">
    ```yaml theme={null}
    eventHandlers:
      - event: Swap(indexed address,uint256,uint256,uint256,uint256,indexed address)
        handler: handleSwap
        calls:
          getReserves:
            label: getReserves
            call: Pair[event.address].getReserves()
          token0:
            label: getToken0
            call: Pair[event.address].token0()
          token1:
            label: getToken1
            call: Pair[event.address].token1()
    ```
  </Tab>

  <Tab title="Mapping Code">
    ```typescript theme={null}
    import { Swap } from '../generated/Contract/UniswapV2Pair'
    import { Pair, Token } from '../generated/schema'
    import { ethereum } from '@graphprotocol/graph-ts'

    export function handleSwap(event: Swap): void {
      let pair = Pair.load(event.address.toHex())
      if (pair == null) {
        pair = new Pair(event.address.toHex())
      }
      
      // Access pre-declared call results
      // These were already fetched in parallel before this handler ran
      let reservesCall = ethereum.call(
        event.address,
        'getReserves',
        []
      )
      
      if (!reservesCall.reverted) {
        let reserves = reservesCall.value
        pair.reserve0 = reserves[0].toBigInt()
        pair.reserve1 = reserves[1].toBigInt()
      }
      
      pair.save()
    }
    ```
  </Tab>
</Tabs>

## ABI Configuration

ABIs must be specified for all contracts your mapping interacts with:

<ParamField path="name" type="String" required>
  The name used to reference this ABI in the mapping code and elsewhere in the manifest.

  <Expandable title="Example">
    ```yaml theme={null}
    name: ERC20
    ```
  </Expandable>
</ParamField>

<ParamField path="file" type="Path" required>
  The path to the ABI JSON file.

  <Expandable title="Example">
    ```yaml theme={null}
    file: ./abis/ERC20.json
    ```
  </Expandable>
</ParamField>

### ABI Example

```yaml theme={null}
abis:
  - name: ERC20
    file: ./abis/ERC20.json
  - name: UniswapV2Factory
    file: ./abis/UniswapV2Factory.json
  - name: UniswapV2Pair
    file: ./abis/UniswapV2Pair.json
```

## Complete Mapping Examples

<Tabs>
  <Tab title="Basic ERC20">
    ```yaml theme={null}
    mapping:
      kind: ethereum/events
      apiVersion: 0.0.7
      language: wasm/assemblyscript
      entities:
        - User
        - Transfer
        - Approval
      abis:
        - name: ERC20
          file: ./abis/ERC20.json
      eventHandlers:
        - event: Transfer(indexed address,indexed address,uint256)
          handler: handleTransfer
        - event: Approval(indexed address,indexed address,uint256)
          handler: handleApproval
      file: ./src/erc20.ts
    ```
  </Tab>

  <Tab title="With Call Handlers">
    ```yaml theme={null}
    mapping:
      kind: ethereum/events
      apiVersion: 0.0.7
      language: wasm/assemblyscript
      entities:
        - Pair
        - Swap
        - Mint
        - Burn
      abis:
        - name: UniswapV2Pair
          file: ./abis/UniswapV2Pair.json
      eventHandlers:
        - event: Swap(indexed address,uint256,uint256,uint256,uint256,indexed address)
          handler: handleSwap
        - event: Mint(indexed address,uint256,uint256)
          handler: handleMint
        - event: Burn(indexed address,uint256,uint256,indexed address)
          handler: handleBurn
      callHandlers:
        - function: sync()
          handler: handleSync
      file: ./src/pair.ts
    ```
  </Tab>

  <Tab title="With Block Handlers">
    ```yaml theme={null}
    mapping:
      kind: ethereum/events
      apiVersion: 0.0.7
      language: wasm/assemblyscript
      entities:
        - Protocol
        - Statistics
      abis:
        - name: Protocol
          file: ./abis/Protocol.json
      eventHandlers:
        - event: StateChanged(uint256)
          handler: handleStateChanged
      blockHandlers:
        - handler: handleBlock
          filter:
            kind: call
      file: ./src/protocol.ts
    ```
  </Tab>

  <Tab title="With Pre-declared Calls">
    ```yaml theme={null}
    mapping:
      kind: ethereum/events
      apiVersion: 0.0.7
      language: wasm/assemblyscript
      entities:
        - Pair
        - Token
      abis:
        - name: UniswapV2Pair
          file: ./abis/UniswapV2Pair.json
        - name: ERC20
          file: ./abis/ERC20.json
      eventHandlers:
        - event: Swap(indexed address,uint256,uint256,uint256,uint256,indexed address)
          handler: handleSwap
          calls:
            getReserves:
              label: getReserves
              call: UniswapV2Pair[event.address].getReserves()
            token0Symbol:
              label: token0Symbol
              call: ERC20[UniswapV2Pair[event.address].token0()].symbol()
      file: ./src/pair.ts
    ```
  </Tab>
</Tabs>

## Best Practices

<AccordionGroup>
  <Accordion title="Choose the Right Handler Type">
    * **Event handlers**: Best for most use cases. Fast and efficient.
    * **Call handlers**: Use when you need to track function calls that don't emit events.
    * **Block handlers**: Use sparingly, only for time-based aggregations or when you absolutely need to process every block.
  </Accordion>

  <Accordion title="Use Pre-declared Calls">
    Pre-declared calls (available from spec 1.2.0+) can significantly improve indexing performance by:

    * Fetching data in parallel before the handler runs
    * Reducing the number of RPC calls during sync
    * Making your code cleaner

    Use them whenever your handler needs to make contract calls.
  </Accordion>

  <Accordion title="Specify Event Signatures Correctly">
    Common mistakes:

    * Using `uint` instead of `uint256`
    * Missing `indexed` keyword
    * Wrong parameter order
    * Using alias types

    Always copy the exact signature from your contract's ABI.
  </Accordion>

  <Accordion title="Handle Null Cases">
    Always check if entities exist before using them:

    ```typescript theme={null}
    let entity = Entity.load(id)
    if (entity == null) {
      entity = new Entity(id)
      // Set default values
    }
    ```
  </Accordion>

  <Accordion title="Keep Handlers Fast">
    * Avoid complex computations in handlers
    * Don't load entities unnecessarily
    * Use batch operations when possible
    * Minimize contract calls (use pre-declared calls instead)
  </Accordion>

  <Accordion title="List All Affected Entities">
    The `entities` array should include all entities that your mapping creates or modifies. This:

    * Documents your mapping's behavior
    * Helps with debugging
    * May be used for optimization in future versions
  </Accordion>
</AccordionGroup>

## Handler Execution Order

Within a single transaction or block, handlers execute in this order:

1. **Call handlers** - In the order calls were made
2. **Event handlers** - In the order events were emitted
3. **Block handlers** - After all other handlers

If you have multiple data sources, their handlers can interleave based on the actual order of events/calls in the block.

## Error Handling

By default, any error in a handler will cause the subgraph to stop syncing. To allow handlers to fail without stopping the subgraph:

1. Set `specVersion` to `0.0.4` or higher
2. Add `nonFatalErrors` to the `features` list
3. Use try-catch or if-null checks in your mapping code

```yaml theme={null}
specVersion: 0.0.4
features:
  - nonFatalErrors
```

## Next Steps

<CardGroup cols={2}>
  <Card title="Manifest Spec" icon="file-code" href="/api/manifest-spec">
    View complete manifest specification
  </Card>

  <Card title="Data Sources" icon="database" href="/api/data-sources">
    Learn about data source configuration
  </Card>
</CardGroup>
