Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .trunk/trunk.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ actions:
Runs codegen for indexer-envio (to produce the generated/ types) then
typechecks both workspaces. Combined into one action so the generated
module is guaranteed to exist before tsc runs.
run: pnpm indexer:celo-mainnet:codegen && pnpm --filter @mento-protocol/ui-dashboard --filter @mento-protocol/indexer-envio typecheck
run: pnpm indexer:codegen && pnpm --filter @mento-protocol/ui-dashboard --filter @mento-protocol/indexer-envio typecheck
triggers:
- git_hooks: [pre-push]
- id: test-pre-push
Expand Down
182 changes: 63 additions & 119 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,41 +1,44 @@
# Mento Monitoring Monorepo

Real-time monitoring infrastructure for Mento v3 on-chain pools — an [Envio HyperIndex](https://docs.envio.dev/) indexer paired with a Next.js 16 + Plotly.js dashboard.
Real-time monitoring infrastructure for Mento v3 on-chain pools — a multichain [Envio HyperIndex](https://docs.envio.dev/) indexer paired with a Next.js 16 + Plotly.js dashboard.

**Live dashboard:** [monitoring.mento.org](https://monitoring.mento.org)

## Packages

| Package | Description |
| ----------------------------------- | ------------------------------------------------------------------------------ |
| [`indexer-envio`](./indexer-envio/) | Envio HyperIndex indexer for Celo + Monad (FPMM pools + VirtualPools) |
| [`ui-dashboard`](./ui-dashboard/) | Next.js 16 + Plotly.js monitoring dashboard with multi-chain network switching |
| [`shared-config`](./shared-config/) | Shared deployment config (chain ID → treb namespace mappings) |
| Package | Description |
| ----------------------------------- | ------------------------------------------------------------------- |
| [`indexer-envio`](./indexer-envio/) | Envio HyperIndex indexer Celo + Monad multichain |
| [`ui-dashboard`](./ui-dashboard/) | Next.js 16 + Plotly.js dashboard with multi-chain network switching |
| [`shared-config`](./shared-config/) | Shared deployment config (chain ID → treb namespace mappings) |

## Architecture

```text
┌─────────────────┐ ┌──────────────────┐ ┌────────────────┐
│ Celo Chain │────▶│ Envio HyperIndex │────▶│ Hasura │
│ (RPC / GRPC) │ │ (Hosted) │ │ (GraphQL API) │
└─────────────────┘ └──────────────────┘ └───────┬────────┘
┌──────▼──────┐
│ Next.js │
│ Dashboard │
│ (Vercel) │
└─────────────┘
┌──────────────────────┐ ┌──────────────────┐ ┌────────────────┐
│ Celo + Monad Chains │────▶│ Envio HyperIndex │────▶│ Hasura │
│ (HyperSync / RPC) │ │ (Hosted, mento) │ │ (GraphQL API) │
└──────────────────────┘ └──────────────────┘ └───────┬────────┘
┌──────▼──────┐
│ Next.js │
│ Dashboard │
│ (Vercel) │
└─────────────┘
```

The indexer runs on Envio's hosted free tier. Each deploy produces a new GraphQL endpoint hash. The dashboard reads from this endpoint via Hasura's GraphQL API.
Both Celo Mainnet (42220) and Monad Mainnet (143) are served from a single Envio project (`mento`) using `config.multichain.mainnet.yaml`. Pool IDs are namespaced as `{chainId}-{address}` to prevent cross-chain collisions.

**Static production endpoint:** `https://indexer.hyperindex.xyz/2f3dd15/v1/graphql`

## Networks

| Network | Chain ID | Status |
| ------------- | -------- | ----------------------------- |
| Celo Mainnet | 42220 | ✅ Live |
| Celo Sepolia | 44787 | ✅ Live |
| Monad Mainnet | — | ⏳ Blocked on contract deploy |
| Network | Chain ID | Status |
| ------------- | -------- | ------- |
| Celo Mainnet | 42220 | ✅ Live |
| Monad Mainnet | 143 | ✅ Live |
| Celo Sepolia | 11142220 | ✅ Live |
| Monad Testnet | 10143 | ✅ Live |

## Getting Started

Expand All @@ -54,15 +57,14 @@ pnpm install
### Run the Indexer (local)

```bash
# Celo Sepolia
pnpm indexer:celo-sepolia:codegen && pnpm indexer:celo-sepolia:dev
# Multichain (Celo + Monad mainnet) — default
pnpm indexer:codegen && pnpm indexer:dev

# Celo Mainnet
pnpm indexer:celo-mainnet:codegen && pnpm indexer:celo-mainnet:dev
# Celo Sepolia (testnet)
pnpm indexer:celo-sepolia:codegen && pnpm indexer:celo-sepolia:dev

# Monad Testnet / Mainnet
# Monad Testnet
pnpm indexer:monad-testnet:codegen && pnpm indexer:monad-testnet:dev
pnpm indexer:monad-mainnet:codegen && pnpm indexer:monad-mainnet:dev
```

### Run the Dashboard
Expand All @@ -71,132 +73,74 @@ pnpm indexer:monad-mainnet:codegen && pnpm indexer:monad-mainnet:dev
pnpm dashboard:dev
```

The dashboard connects to Hasura (local or hosted) to display real-time pool data.

## Environment Variables

### Indexer

Create `indexer-envio/.env` from `indexer-envio/.env.example`:

| Variable | Description | Default |
| ------------------- | ---------------------------- | ---------- |
| `ENVIO_API_TOKEN` | Envio platform API token | — |
| `ENVIO_RPC_URL` | Celo RPC endpoint | — |
| `ENVIO_START_BLOCK` | Block to start indexing from | `60664513` |
| Variable | Description |
| ------------------------- | ------------------------------------- |
| `ENVIO_RPC_URL_42220` | Celo Mainnet RPC endpoint |
| `ENVIO_RPC_URL_143` | Monad Mainnet RPC endpoint |
| `ENVIO_START_BLOCK_CELO` | Celo start block (default: 60664500) |
| `ENVIO_START_BLOCK_MONAD` | Monad start block (default: 60730000) |

### Dashboard

The dashboard supports multiple network targets via `_<NETWORK>` suffix env vars:

| Variable | Description |
| --------------------------------------------- | ------------------------------------------------ |
| `NEXT_PUBLIC_HASURA_URL_CELO_MAINNET_HOSTED` | Hasura/GraphQL endpoint — Celo Mainnet (hosted) |
| `NEXT_PUBLIC_HASURA_URL_MONAD_MAINNET_HOSTED` | Hasura/GraphQL endpoint — Monad Mainnet (hosted) |
| `NEXT_PUBLIC_HASURA_URL_MONAD_TESTNET_HOSTED` | Hasura/GraphQL endpoint — Monad Testnet (hosted) |
| `NEXT_PUBLIC_HASURA_URL_CELO_SEPOLIA_HOSTED` | Hasura/GraphQL endpoint — Celo Sepolia (hosted) |
| `NEXT_PUBLIC_HASURA_URL_CELO_MAINNET` | Hasura endpoint — Celo Mainnet (local) |
| `NEXT_PUBLIC_HASURA_URL_CELO_SEPOLIA` | Hasura endpoint — Celo Sepolia (local) |
| `NEXT_PUBLIC_EXPLORER_URL_CELO_MAINNET` | Block explorer — Celo Mainnet |
| `NEXT_PUBLIC_EXPLORER_URL_CELO_SEPOLIA` | Block explorer — Celo Sepolia |
| `UPSTASH_REDIS_REST_URL` | Address labels storage (Upstash Redis) |
| `UPSTASH_REDIS_REST_TOKEN` | Address labels Redis auth token |
| `BLOB_READ_WRITE_TOKEN` | Vercel Blob token for daily label backups |
| Variable | Description |
| -------------------------------------------- | ------------------------------------------------- |
| `NEXT_PUBLIC_HASURA_URL_MULTICHAIN_HOSTED` | Shared multichain GraphQL endpoint (Celo + Monad) |
| `NEXT_PUBLIC_HASURA_URL_CELO_SEPOLIA_HOSTED` | Celo Sepolia hosted endpoint |
| `UPSTASH_REDIS_REST_URL` | Address labels storage (Upstash Redis) |
| `UPSTASH_REDIS_REST_TOKEN` | Address labels Redis auth token |
| `BLOB_READ_WRITE_TOKEN` | Vercel Blob token for daily label backups |

Production env vars are managed by Terraform — do not edit them in the Vercel dashboard. See [`terraform/`](./terraform/) and [`docs/deployment.md`](./docs/deployment.md).

## Contract Addresses

Contract addresses and ABIs are sourced from the published [`@mento-protocol/contracts`](https://www.npmjs.com/package/@mento-protocol/contracts) npm package — no vendored JSON files. The active treb deployment namespace per chain is declared in [`shared-config/deployment-namespaces.json`](./shared-config/deployment-namespaces.json):

```json
{
"42220": "mainnet",
"11142220": "testnet-v2-rc5"
}
```

**To promote a new treb deployment** (e.g. after a new `mento-deployments-v2` release):

1. Publish a new `@mento-protocol/contracts` version from `mento-deployments-v2`
2. Update the package version in `indexer-envio/package.json` and `ui-dashboard/package.json`
3. Update the namespace string(s) in `shared-config/deployment-namespaces.json`
4. Run `pnpm install`
Production env vars are managed by Terraform. See [`terraform/`](./terraform/).

## Deployment

### Indexer → Envio Hosted

Each network has a dedicated deploy branch Envio watches:

| Network | Deploy Branch |
| ------------- | ---------------------- |
| Celo Mainnet | `deploy/celo-mainnet` |
| Celo Sepolia | `deploy/celo-sepolia` |
| Monad Mainnet | `deploy/monad-mainnet` |
| Monad Testnet | `deploy/monad-testnet` |

Push to trigger a redeploy:
Push to the `envio` branch to trigger a hosted reindex:

```bash
pnpm deploy:indexer celo-mainnet
# or run without args to be prompted:
pnpm deploy:indexer
# or push directly:
git push origin main:deploy/celo-mainnet
```

> ⚠️ **Celo Sepolia endpoint changes on each Envio redeploy.** After redeploying the Celo Sepolia indexer, update `hasura_url_celo_sepolia_hosted` in `terraform/terraform.tfvars` and run `pnpm infra:apply`.
The `mento` project on [Envio Cloud](https://envio.dev/app/mento-protocol/mento) watches this branch.

### Dashboard → Vercel

Vercel's native Git integration watches `main` — every push that touches `ui-dashboard/` auto-deploys the dashboard to [monitoring.mento.org](https://monitoring.mento.org).
Every push to `main` that touches `ui-dashboard/` auto-deploys to [monitoring.mento.org](https://monitoring.mento.org).

All infrastructure (Vercel project, env vars, Upstash Redis, custom domain) is managed by Terraform:
Infrastructure (Vercel project, env vars, Upstash Redis) is managed by Terraform:

```bash
pnpm infra:plan # preview changes
pnpm infra:apply # apply changes
```

See [`docs/deployment.md`](./docs/deployment.md) for the full setup guide and troubleshooting.

## CI

GitHub Actions runs on every PR:
## Contract Addresses

- ESLint 10 (no `eslint-config-next` — uses `@eslint/js` + `typescript-eslint` + `@eslint-react`)
- Vitest (105 tests)
- TypeScript typecheck
- Codecov coverage reporting
Sourced from the published [`@mento-protocol/contracts`](https://www.npmjs.com/package/@mento-protocol/contracts) npm package. The active treb deployment namespace per chain is declared in [`shared-config/deployment-namespaces.json`](./shared-config/deployment-namespaces.json).

## Key Files

| What | Where |
| ------------------------------ | -------------------------------------------- |
| **Deployment namespace map** | `shared-config/deployment-namespaces.json` |
| Indexer schema | `indexer-envio/schema.graphql` |
| Event handlers | `indexer-envio/src/EventHandlers.ts` |
| Contract address resolution | `indexer-envio/src/contractAddresses.ts` |
| Celo mainnet config | `indexer-envio/config.celo.mainnet.yaml` |
| Celo Sepolia config | `indexer-envio/config.celo.sepolia.yaml` |
| Monad mainnet/testnet configs | `indexer-envio/config.monad.*.yaml` |
| Dashboard app | `ui-dashboard/src/app/` |
| Address book page | `ui-dashboard/src/app/address-book/page.tsx` |
| Address labels API | `ui-dashboard/src/app/api/address-labels/` |
| Address labels storage | `ui-dashboard/src/lib/address-labels.ts` |
| Network defs + contract labels | `ui-dashboard/src/lib/networks.ts` |
| GraphQL queries | `ui-dashboard/src/lib/queries.ts` |
| Pool type helper | `ui-dashboard/src/lib/tokens.ts` |
| Terraform infrastructure | `terraform/` |
| Deployment guide | `docs/deployment.md` |
| Technical spec | `SPEC.md` |
| Roadmap | `docs/ROADMAP.md` |
| What | Where |
| ------------------------- | ---------------------------------------------- |
| Indexer schema | `indexer-envio/schema.graphql` |
| Event handlers | `indexer-envio/src/EventHandlers.ts` |
| Pool ID helpers | `indexer-envio/src/helpers.ts` |
| Multichain config | `indexer-envio/config.multichain.mainnet.yaml` |
| Indexer status + endpoint | `indexer-envio/STATUS.md` |
| Dashboard app | `ui-dashboard/src/app/` |
| Network defs | `ui-dashboard/src/lib/networks.ts` |
| GraphQL queries | `ui-dashboard/src/lib/queries.ts` |
| Terraform infrastructure | `terraform/` |

## Documentation

- [`SPEC.md`](./SPEC.md) — Full technical specification
- [`docs/ROADMAP.md`](./docs/ROADMAP.md) — Current state + upcoming work
- [`docs/BACKLOG.md`](./docs/BACKLOG.md) — Detailed task backlog
- [`docs/deployment.md`](./docs/deployment.md) — Deployment guide
- [`indexer-envio/README.md`](./indexer-envio/README.md) — Indexer reference
- [`indexer-envio/STATUS.md`](./indexer-envio/STATUS.md) — Current sync state + endpoint
- [`docs/deployment.md`](./docs/deployment.md) — Full deployment guide
12 changes: 10 additions & 2 deletions indexer-envio/.env.example
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
# To create or update a token visit https://envio.dev/app/api-tokens
ENVIO_API_TOKEN="<YOUR-API-TOKEN>"
ENVIO_RPC_URL="http://34.32.123.41:8545"
ENVIO_START_BLOCK="60548751"

# Multichain mode — set per-chain RPC endpoints.
# Do NOT set the generic ENVIO_RPC_URL in multichain mode; it would route all
# chains to the same endpoint and produce incorrect RPC reads.
ENVIO_RPC_URL_42220="https://forno.celo.org"
ENVIO_RPC_URL_143="https://rpc2.monad.xyz"

# Optional start block overrides (defaults are set in EventHandlers.ts)
# ENVIO_START_BLOCK_CELO="60664500"
# ENVIO_START_BLOCK_MONAD="60730000"
11 changes: 7 additions & 4 deletions indexer-envio/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,11 @@ pnpm test # Run tests (mocha + chai)

Copy `.env.example` → `.env` and set:

- `ENVIO_API_TOKEN` — Get from <https://envio.dev/app/api-tokens>
- `ENVIO_RPC_URL` — Celo RPC endpoint
- `ENVIO_START_BLOCK` — Block number to start indexing from
- `ENVIO_RPC_URL_42220` — Celo Mainnet RPC endpoint (e.g. `https://forno.celo.org`)
- `ENVIO_RPC_URL_143` — Monad Mainnet RPC endpoint (e.g. `https://rpc2.monad.xyz`)
- `ENVIO_START_BLOCK_CELO` — (optional) Celo start block, defaults to 60664500
- `ENVIO_START_BLOCK_MONAD` — (optional) Monad start block, defaults to 60730000

For Celo Sepolia: use root `pnpm indexer:celo-sepolia:dev`. For Celo mainnet: `pnpm indexer:celo-mainnet:dev`. For Monad: `pnpm indexer:monad-mainnet:dev` or `pnpm indexer:monad-testnet:dev`.
Do **not** set the generic `ENVIO_RPC_URL` in multichain mode — it would route all chains to the same endpoint and produce incorrect RPC reads for chain-specific calls.

Default (multichain Celo + Monad mainnet): `pnpm indexer:codegen && pnpm indexer:dev`. For Celo Sepolia testnet: `pnpm indexer:celo-sepolia:dev`. For Monad Testnet: `pnpm indexer:monad-testnet:dev`.
Loading
Loading