> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sqd.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Direct RPC queries

> Query chain state directly via wrapped RPC calls.

The `Contract` classes generated by `squid-evm-typegen` wrap `eth_call` state queries. They need a JSON-RPC endpoint to talk to: the [Portal data source](../evm-stream) does not use one and the [handler context](../batch-processor#handler-context) provides no built-in chain access, so construct a client explicitly with `RpcClient` from `@subsquid/rpc-client`:

```typescript theme={"system"}
import {RpcClient} from '@subsquid/rpc-client'

const rpc = new RpcClient({
  url: process.env.RPC_ETH_HTTP!,
  rateLimit: 10 // requests per second
})
```

We recommend using a private endpoint from e.g. [BlastAPI](https://blastapi.io/) or the SQD Cloud's [RPC addon](/en/cloud/resources/rpc-proxy), and setting it via an environment variable. You can define the `RPC_ETH_HTTP` in three ways:

* for local runs, simply update the local `.env` file;
* for squids deployed to Cloud define it as a [secret](/en/cloud/resources/env-variables) on your Cloud account;
* if you are using the [RPC addon](/en/cloud/resources/rpc-proxy), leave it to the Cloud to define it for you.

## `Contract` class

The EVM contract state is accessed using the `Contract` class generated by `squid-evm-typegen`. Its constructor takes

1. a chain access object - anything of the shape `{_chain: {client}}`, where `client` has a `call(method, params)` method; an `RpcClient` instance fits;
2. a block reference - any object with a `height` field; the state is queried at that block height;
3. the contract address.

For example, assume that we index an ERC721 contract. Typescript ABI module generated with `squid-evm-typegen` will contain the following class:

```typescript theme={"system"}
export class Contract extends ContractBase {
  //...
  balanceOf(owner: string): Promise<bigint> {
    return this.eth_call(balanceOf, {owner})
  }
  //...
}
```

Now suppose we want to query our contract from the batch handler. Create a `Contract` with the RPC client and the current block, then query the contract state at that block:

```typescript theme={"system"}
import {run} from '@subsquid/batch-processor'
import {TypeormDatabase} from '@subsquid/typeorm-store'
// ...
const CONTRACT_ADDRESS = '0xb654611f84a8dc429ba3cb4fda9fad236c505a1a'

run(dataSource, new TypeormDatabase({supportHotBlocks: true}), async ctx => {
  for (const block of ctx.blocks) {
    const contract = new abi.Contract(
      {_chain: {client: rpc}},
      {height: block.header.number},
      CONTRACT_ADDRESS
    )
    // query the contract state at the current block
    const balance = await contract.balanceOf('0xd8da6bf26964af9d7eed9e03e53415d37aa96045')
    // ...
  }
})
```

## Batch state queries

The [MakerDAO Multicall contract](https://github.com/makerdao/multicall) was designed to batch multiple state queries into a single contract call. In the context of indexing, it normally significantly improves the indexing speed since JSON RPC calls are typically the bottleneck.

Multicall contracts are deployed in many EVM chains, see the [contract repo](https://github.com/makerdao/multicall) for addresses. You can use any of them with a `multicall` Typescript module that is generated when running `squid-evm-typegen` with `--multicall` option. The module exports a `Multicall` class with this method:

```typescript theme={"system"}
tryAggregate<TF extends AbiFunction<any, any>>(
  func: TF,
  calls: (readonly [address: string, args: FunctionArguments<TF>])[],
  pageSize?: number
): Promise<MulticallResult<TF>[]>
```

The arguments are as follows:

* `func`: the contract function to be called
* `calls`: an array of tuples `[contractAddress: string, args]`. Each specified contract will be called with the specified arguments.
* `pageSize` is an optional maximum number of calls per JSON-RPC request. Large page sizes may cause timeouts.

The generated class also accepts one shared contract address plus an array of
argument objects, or an array of `[function, address, arguments]` tuples for
mixed calls. `aggregate()` has the same overloads but throws when a call fails.

`Multicall` is constructed exactly like the other generated [`Contract` classes](#contract-class) - with a chain access object, a block reference and the address of a deployed Multicall contract. A typical usage is as follows:

```typescript title="src/main.ts" theme={"system"}
import { run } from '@subsquid/batch-processor'
import { createLogger } from '@subsquid/logger'
import { RpcClient } from '@subsquid/rpc-client'
import { TypeormDatabase } from '@subsquid/typeorm-store'
// generated by evm-typegen
import { functions } from './abi/mycontract'
import { Multicall } from './abi/multicall'

const MY_CONTRACT = '0xac5c7493036de60e63eb81c5e9a440b42f47ebf5'
const MULTICALL_CONTRACT = '0x5ba1e12693dc8f9c48aad8770482f4739beed696'

const rpc = new RpcClient({url: process.env.RPC_ETH_HTTP!})
const log = createLogger('sqd:processor:mapping')

run(dataSource, new TypeormDatabase({supportHotBlocks: true}), async (ctx) => {
  for (let c of ctx.blocks) {
    // some logic
  }
  const lastBlock = ctx.blocks[ctx.blocks.length - 1]
  const multicall = new Multicall(
    {_chain: {client: rpc}},
    {height: lastBlock.header.number},
    MULTICALL_CONTRACT
  )
  // call MY_CONTRACT.myContractMethod('foo') and MY_CONTRACT.myContractMethod('bar')
  const args = ['foo', 'bar']
  const results = await multicall.tryAggregate(
    functions.myContractMethod,
    args.map(value => [MY_CONTRACT, {value}] as const),
    100
  )

  results.forEach((res, i) => {
    if (res.success) {
      log.info(`Result for argument ${args[i]} is ${res.value}`)
    }
  })
})
```
