> For the complete documentation index, see [llms.txt](https://galactic-bridge.gitbook.io/galactic-bridge-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://galactic-bridge.gitbook.io/galactic-bridge-docs/rpc-nodes.md).

# RPC nodes

Most of the bridge works over ordinary contract calls, which any public node handles. Finding a **bridge adapter** is different: it requires reading historical event logs, and free public nodes vary wildly in what they allow.

## What goes wrong

| Symptom                                        | What the node is doing                                                                                |
| ---------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
| `limit exceeded`                               | Refuses `eth_getLogs` entirely, at any range.                                                         |
| `archive request required`                     | Serves only the newest few thousand blocks.                                                           |
| `ranges over N blocks are not supported`       | Caps the range at 100–500 blocks, too small to scan with.                                             |
| `null` for an older transaction                | Prunes the transaction index, so old hashes look missing.                                             |
| Requests start failing part-way through a scan | Rate-limiting. A node can pass a short test and still collapse under a few hundred requests in a row. |

The bridge is built to survive all of this. It rotates between nodes, retries, and **never treats an RPC error as "no data"** — an unreachable node must not be mistaken for a token that does not exist.

## Switching nodes during a scan

The last row above is the awkward one. A full adapter scan is several hundred `eth_getLogs` requests in a row, while the check that picks a node is a single short request. A node can pass that check and then start refusing requests once the real work begins.

So the scan is not tied to the node it started on. When requests begin failing in a way that looks like the node rather than the data, the bridge:

1. moves to the next node in the list,
2. **resumes from the same block range**, and
3. carries on — nothing is rescanned, and the search is not abandoned.

This distinction matters. A failed request and an empty block range look identical from the outside, and treating one as the other is how a search quietly returns "nothing found" for a token that is really there. The two cases are tracked separately, which is what makes the switch possible.

## Checking every network

```bash
cd backend && node tools/checkLogsRpc.js
```

The script reports, for each network, whether its nodes serve fresh logs, logs 50,000 blocks back, and logs 500,000 blocks back — then gives a verdict.

{% hint style="info" %}
The check uses short requests, so a positive verdict means the node *can* serve deep logs — not that it will survive a full scan. That is why the bridge also switches nodes while scanning.
{% endhint %}

To find a working node from a list of candidates:

```bash
cd backend && node tools/findRpc.js
```

## Adding an archive node

When no free node works for a network, point the bridge at one with archive access. No code changes are needed:

```
LOGS_RPC_BSC=https://your-node/your-key
```

Several nodes can be listed, separated by commas. They are tried in order, and the scan continues on the next one if the current node starts refusing requests:

```
LOGS_RPC_BSC=https://primary-node/your-key,https://backup-node/your-key
```

Chain keys: `eth`, `bsc`, `base`, `arb`, `poly`, `op`, `avax`, `mantle`, `hyperevm`, `ink`, `xlayer`, `plasma`, `robinhood`, `arc`.

Free tiers that work: [NodeReal](https://nodereal.io) (archive on BNB Chain and Ethereum), [dRPC](https://drpc.org), [Alchemy](https://alchemy.com), [Chainstack](https://chainstack.com). Note that some providers cap `eth_getLogs` ranges on their free plans, which makes them unsuitable for scanning even though ordinary calls work fine.

## Backup nodes for ordinary calls

A keyed node can also be registered as a fallback for regular calls — used **only** when the public ones fail, so it does not burn quota:

```
RPC_FALLBACK_AVAX=https://your-node/your-key
```

This helps on networks whose public endpoints rate-limit aggressively. Note the difference in priority, which is deliberate:

| Variable               | Position | Why                                                                                  |
| ---------------------- | -------- | ------------------------------------------------------------------------------------ |
| `RPC_<CHAIN>`          | First    | An explicit override for ordinary calls.                                             |
| `RPC_FALLBACK_<CHAIN>` | Last     | Public nodes handle ordinary calls fine, so your quota is spent only when they fail. |
| `LOGS_RPC_<CHAIN>`     | First    | Public nodes almost never serve deep logs, so trying them first only wastes time.    |

## Rate limits when self-hosting

A single token search can trigger a few hundred RPC requests, so the backend caps how often the expensive endpoints can be called from one IP:

| Variable                 | Endpoint           | Default           |
| ------------------------ | ------------------ | ----------------- |
| `RL_SCAN_MAX`            | `/api/scan-token`  | 15 per minute     |
| `RL_FIND_MAX`            | `/api/find-params` | 50 per minute     |
| `RL_MAX`, `RL_WINDOW_MS` | everything         | 60 per 15 seconds |

Search results are also cached in memory, so repeated lookups of the same token cost nothing at all.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://galactic-bridge.gitbook.io/galactic-bridge-docs/rpc-nodes.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
