> For the complete documentation index, see [llms.txt](https://docs.envio.dev/llms.txt).

# MIP-16 query methods

[MIP-16](https://github.com/monad-crypto/MIPs/blob/main/MIPs/MIP-16.md) adds RPC query methods that filter on the server, return only the fields you select, and can join related objects, such as each log's transaction and block. HyperRPC serves them on every [supported network](https://docs.envio.dev/docs/HyperRPC/hyperrpc-supported-networks.md), mainnets and testnets alike, alongside the [standard methods](https://docs.envio.dev/docs/HyperRPC/overview-hyperrpc.md#supported-methods).

## Methods

| Method | Filters | Status |
| --- | --- | --- |
| `eth_queryBlocks` | `miner` | Live |
| `eth_queryTransactions` | `from`, `to`, function `selector` | Live |
| `eth_queryLogs` | `address`, `topics` | Live |
| `eth_queryTraces` |  | Coming soon |
| `eth_queryTransfers` |  | Coming soon |

See the [MIP-16 spec](https://github.com/monad-crypto/MIPs/blob/main/MIPs/MIP-16.md) and its [latest revision](https://github.com/monad-crypto/MIPs/pull/89) for every filter and field.

## Endpoints

Send MIP-16 requests to the same HyperRPC endpoint you use for standard methods on any network:

```text
https://<network>.rpc.hypersync.xyz/<api-token>
```

Find the endpoint for each network on the [supported networks](https://docs.envio.dev/docs/HyperRPC/hyperrpc-supported-networks.md) page. Requests need an API token. See [API Tokens](/docs/HyperSync/api-tokens) for how to create one.

## Example

The request works the same way on every network. This one runs on Monad and returns the most recent WMON `deposit()` calls, newest first. It filters by the WMON contract address and the `deposit()` function selector.

```bash
curl https://monad.rpc.hypersync.xyz/<api-token> \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "eth_queryTransactions",
    "params": [{
      "filter": {
        "to": "0x3bd359C1119dA7Da1D913D1C4D2B7c461115433A",
        "selector": "0xd0e30db0"
      },
      "fields": {
        "transactions": ["hash", "from", "value", "blockNumber"]
      },
      "order": "desc"
    }]
  }'
```

The first page may be empty, so keep paging (see below). A page with a match looks like this:

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "data": {
      "transactions": [
        {
          "blockNumber": "0x725e079",
          "from": "0x39c06b54686b0540d6d57a254b976b1df4310df1",
          "hash": "0xb22654167eb03199c54907d11bc0757003576ee90f41232394bb596c80e2d49f",
          "value": "0x1b1ae4d6e2ef500000"
        }
      ]
    },
    "fromBlock": {
      "number": "0x725e3d2",
      "hash": "0xbb79588ba79c36ab2768ead580c0e84175f29cfd229d714aa1ca7b1b1e1a0cbb",
      "parentHash": "0x9c021696e3622c938b0f5b0ff8311c7f1e4a2181b8f712a8951072680b1b46a5"
    },
    "toBlock": {
      "number": "0x0",
      "hash": "0x0c47353304f22b1c15706367d739b850cda80b5c87bbc335014fef3d88deaac9",
      "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
    },
    "cursorBlock": {
      "number": "0x725dfeb",
      "hash": "0x94a8412730cffc4c3ce9b2c6b0eefd8fbef93b50f664646d8e0c0d3d2dfdd7f9",
      "parentHash": "0x778b1459435ef59b8b1c9ec8c90023126bec785b1bffe52032a699ea0347104c"
    }
  }
}
```

## Request parameters

| Parameter | Required | Description |
| --- | --- | --- |
| `fromBlock` | No | Start of the range, as a hex block number such as `0x725e079` or a tag such as `latest` or `earliest`. With `desc`, this is the newest block |
| `toBlock` | No | End of the range, as a hex block number or a tag. With `desc`, this is the oldest block |
| `order` | No | `asc` (default, oldest first) or `desc` (newest first) |
| `target` | No | Target number of results per page, as hex (for example `0x64`). Joined objects don't count towards it |
| `filter` | No | Method-specific filters, such as `to` and `selector` for transactions |
| `fields` | No | Fields to return, and related objects to join. If you set it, include the method's own type, such as `logs` for `eth_queryLogs` |

## Response fields

| Field | Description |
| --- | --- |
| `data` | The matching results, with only the fields you selected, plus any joined objects |
| `fromBlock` | The first block of the page, with its hash and parent hash |
| `toBlock` | The last block of the requested range |
| `cursorBlock` | The last block this page covers |

## Paging

Every page ends on a whole block, reported as `cursorBlock`. To get the next page, repeat the request with a new `fromBlock`:

| Order | Next `fromBlock` |
| --- | --- |
| `asc` (default) | `cursorBlock` + 1 |
| `desc` | `cursorBlock` - 1 |

A page can return fewer results than `target`, or none. Keep paging from `cursorBlock` until you have the results you need or reach `toBlock`.

## Reorg detection

When you page forwards near the chain tip, compare each page's `fromBlock.parentHash` with the previous page's `cursorBlock.hash`. If they differ, a reorg has replaced blocks you already read, so roll back to the newest block you hold that still matches, and page again from the block after it.

## Errors

| Code | Meaning |
| --- | --- |
| `-32602` | Invalid params, such as an unknown request field or `fields` without the method's own type |
| `-32001` | Some or all of the requested range, including blocks not yet produced, is outside the blocks HyperRPC serves |
| `-32004` | The method isn't supported yet |
| `-32005` | The first block of the range was too large to return in one page |
| HTTP `429` | Rate limited. Wait before retrying |

## Hand this to your coding agent

```text
Using the MIP-16 method eth_queryLogs on Envio HyperRPC, write a Node.js script
that collects every Transfer event from the token contract I name, over the block
range I give, with the sender of each transaction and the timestamp of each block.

- Use https://<network>.rpc.hypersync.xyz/$ENVIO_API_TOKEN for the network I name
- Filter by address and the Transfer topic
- Request logs, transactions and blocks in one call with fields.logs,
  fields.transactions and fields.blocks
- Include the join fields: fields.logs needs transactionHash and blockNumber,
  fields.transactions needs hash and from, fields.blocks needs number and
  timestamp
- Join them with logs.transactionHash = transactions.hash and
  logs.blockNumber = blocks.number
- Send block numbers as 0x-prefixed hex
- Page with cursorBlock: the next request starts at cursorBlock + 1, until
  cursorBlock reaches toBlock
- If the response is HTTP 429, wait and retry

Docs: https://docs.envio.dev/docs/HyperRPC/mip-16
Spec: https://github.com/monad-crypto/MIPs/blob/main/MIPs/MIP-16.md
```
