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

# Indexer

> The persistent source of truth for Geode — indexes on-chain events and serves token, pool, and settlement data.

## What is the Indexer?

The Geode Indexer is a lightweight service that scans Ethereum for Geode protocol events and stores them in a persistent database. It serves as the **single source of truth** for:

* **Launched tokens** — every coin deployed via the [Geocurve](/geocurve)
* **Batch settlements** — clearing prices, matched volumes, and settler fees

<Info>
  The indexer replaces the settler's volatile in-memory token registry. Tokens persist across restarts, and the [settler bot](/settler) automatically syncs its pool list from the indexer every 30 seconds.
</Info>

## Architecture

```
┌─────────────┐                       ┌──────────────────────┐
│  Frontend   │ ◄── GET /tokens ────► │                      │
│  (Launchpad)│ ──► POST /tokens ───► │    Geode Indexer      │
└─────────────┘                       │    (Express + SQLite)  │
                                      │                      │
┌─────────────┐   Polls every 5s      │  ┌────────────────┐  │
│  Ethereum   │ ◄────────────────────►│  │ SQLite (WAL)   │  │
│  (RPC)      │   TokenLaunched       │  │ • tokens       │  │
└─────────────┘   BatchSettled        │  │ • settlements  │  │
                                      │  │ • indexer_state │  │
┌─────────────┐                       │  └────────────────┘  │
│  Settler    │ ◄── GET /tokens ────► │                      │
│  Bot        │   (every 30s sync)    └──────────────────────┘
└─────────────┘
```

The indexer connects three systems:

1. **Ethereum** → polls for on-chain events and writes them to the database
2. **Frontend** → reads token lists, writes new launches via POST
3. **Settler** → syncs pool registrations so every token is automatically settleable

## Hosted Instance

Geode runs a public indexer at:

```
https://indexer.geode.ag
```

Try it now:

```bash theme={null}
curl https://indexer.geode.ag/health
curl https://indexer.geode.ag/tokens
curl https://indexer.geode.ag/stats
```

## Self-Hosting

<Steps>
  <Step title="Clone and install">
    ```bash theme={null}
    git clone https://github.com/Geode-vAMM/geodex.git
    cd geodex/indexer
    npm install
    ```
  </Step>

  <Step title="Configure">
    ```bash theme={null}
    cp .env.example .env
    ```

    Set at minimum:

    * `FACTORY_ADDRESS` — GeodeFactory contract address
    * `HOOK_ADDRESS` — GeodeHook contract address
    * `RPC_URL` — your Ethereum JSON-RPC endpoint
  </Step>

  <Step title="Start">
    ```bash theme={null}
    npm start
    ```

    The indexer will begin polling for events and serving data on port 3004.
  </Step>
</Steps>

## Configuration

| Variable           | Required | Default                               | Description                            |
| ------------------ | -------- | ------------------------------------- | -------------------------------------- |
| `RPC_URL`          | No       | `https://ethereum-rpc.publicnode.com` | Ethereum JSON-RPC endpoint             |
| `FACTORY_ADDRESS`  | ⚠️       | —                                     | GeodeFactory contract address          |
| `HOOK_ADDRESS`     | ⚠️       | —                                     | GeodeHook contract address             |
| `START_BLOCK`      | No       | current                               | Block number to start indexing from    |
| `POLL_INTERVAL_MS` | No       | `5000`                                | How often to scan for new blocks (ms)  |
| `PORT`             | No       | `3004`                                | HTTP API port                          |
| `DATA_DIR`         | No       | `./data`                              | Directory for the SQLite database file |

<Note>
  If neither `FACTORY_ADDRESS` nor `HOOK_ADDRESS` is set, the indexer runs in **API-only mode** — it accepts token registrations via `POST /tokens` but does not poll for on-chain events.
</Note>

## API Reference

### List All Tokens

```
GET /tokens
```

Returns all launched tokens, newest first. Response format:

```json theme={null}
[
  {
    "name": "Meridian",
    "symbol": "MID",
    "tokenAddress": "0x...",
    "poolId": "0x...",
    "deployer": "0x...",
    "totalSupply": "1000000000000000000000000",
    "virtualEthReserve": "5000000000000000000",
    "virtualTokenReserve": "800000000000000000000000",
    "launchedAt": 1715200000000,
    "blockNumber": 19500000
  }
]
```

### Get Token by Address

```
GET /tokens/:address
```

Returns a single token by its contract address. Returns `404` if not found.

### Register a Token

```
POST /tokens
Content-Type: application/json
```

Register a newly launched token. Called by the frontend after a successful Geocurve deployment.

```json theme={null}
{
  "tokenAddress": "0x...",
  "symbol": "MID",
  "name": "Meridian",
  "deployer": "0x...",
  "poolId": "0x...",
  "txHash": "0x...",
  "totalSupply": "1000000000000000000000000",
  "virtualEthReserve": "5000000000000000000",
  "virtualTokenReserve": "800000000000000000000000"
}
```

<Note>
  Duplicate registrations (same `tokenAddress`) are safely ignored with `status: "already_registered"`. The indexer also discovers tokens from on-chain `TokenLaunched` events, so manual registration is a belt-and-suspenders approach.
</Note>

### List Settlements

```
GET /settlements?limit=50&poolId=0x...
```

Returns recent batch settlement events. Both query parameters are optional.

### Statistics

```
GET /stats
```

Returns aggregate indexer statistics:

```json theme={null}
{
  "tokens": 42,
  "settlements": 1337,
  "lastIndexedBlock": 19500000,
  "uptime": 86400
}
```

### Health Check

```
GET /health
```

## Indexed Events

The indexer watches for these on-chain events:

<CardGroup cols={2}>
  <Card title="TokenLaunched" icon="rocket">
    Emitted by GeodeFactory when a new Geocurve token is deployed. Captures name, symbol, deployer, reserves, and royalty configuration.
  </Card>

  <Card title="GeodeBatchSettled" icon="check-double">
    Emitted by GeodeHook after each successful settlement. Records clearing price, matched volume, fees, and settler address.
  </Card>

  <Card title="GeodeCurveSwap" icon="chart-line">
    Emitted on every direct bonding curve swap. Tracks input/output amounts, fees, reserve fee, and updated ETH reserve.
  </Card>

  <Card title="GeodeLaunched" icon="gem">
    Backup event from GeodeHook (fewer fields than Factory's TokenLaunched). Ensures tokens are captured even if the Factory event is missed.
  </Card>
</CardGroup>

## Persistence

The indexer uses **SQLite** with WAL mode for the database. Key tables:

| Table           | Contents                                                  |
| --------------- | --------------------------------------------------------- |
| `tokens`        | All launched tokens with metadata                         |
| `settlements`   | Every batch settlement with clearing price, fees, settler |
| `indexer_state` | Tracks `last_indexed_block` for resumption after restart  |

The database file lives at `$DATA_DIR/geode.db`. On Railway, this is mounted to a persistent volume at `/data` so data survives redeployments.

## Deploying to Railway

The indexer is deployed to Railway with a persistent volume for the SQLite database:

```bash theme={null}
cd indexer
railway login
railway init --name geode-indexer
railway up --detach
railway volume add --mount-path /data
railway variables set RPC_URL=https://ethereum-rpc.publicnode.com FACTORY_ADDRESS=0x... HOOK_ADDRESS=0x... DATA_DIR=/data
railway domain
```

## Settler Integration

The [settler bot](/settler) automatically syncs its pool list from the indexer:

```
INDEXER_URL=https://indexer.geode.ag
```

On startup and every 30 seconds, the settler fetches `GET /tokens` from the indexer and registers any new pools. This means **every token launched on Geode is automatically available for settlement** — no manual pool registration required.

See the [Settler documentation](/settler) for details on running a settlement service.
