Operations
Run locally
Step-by-step for getting the full stack running on a single Windows + WSL2 + Docker host, in the order the components depend on each other. By the end of this you should be able to: hit eth_chainId on the gateway, see a balance in the read API, create a merchant on Pay, create an invoice, and watch settlement detect a payment.
The whole stack is local development. Nothing here is exposed to the public internet. Do not run these commands on a host that the public internet can reach.
Prerequisites
| OS | Windows 10/11 with WSL2 (Ubuntu) |
| Container runtime | Docker Desktop with WSL2 integration or Docker Engine inside WSL |
| Disk | 20 GB free (chain image is large) |
| RAM | 8 GB minimum, 16 GB recommended |
| Tools | curl.exe (or curl from inside WSL), jq (optional) |
| Wallet | MetaMask in your host browser (optional, for the wallet-side check) |
A reasonable check:
wsl -l -v
docker --version
The 5-step quickstart
1. Build and start the chain
cd ~/babychain
docker build -f chain\Dockerfile.babychain -t babychain:local chain
Start the node. The script is mounted read-only so editing chain\babychain_local.sh does not require a rebuild; just restart the container.
2. Start the gateway
cd ~/babychain
docker compose -f gateway\docker-compose.yml up -d
Three containers come up: openresty (:8080), indexer, api (:3000), and postgres (:5432).
3. Start Pay
cd ~/babychain
docker compose -f pay\docker-compose.yml up -d
Three containers: pay-api (:4000), pay-settlement, pay-webhooks, pay-sweep.
4. (Optional) start the explorer and monitoring
docker compose -f explorer\docker-compose.yml up -d
docker compose -f monitoring\docker-compose.yml up -d
5. Verify
curl http://localhost:8080 -X POST -H "Content-Type: application/json" `
--data ''{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}''
You should see {"jsonrpc":"2.0","id":1,"result":"0x07eb"} (2027 in hex).
What runs where
| Service | Port | Container name | Healthcheck |
|---|---|---|---|
evmd (chain) |
8545, 8546, 26657, 1317 | babychain-node |
curl localhost:1317/... |
| OpenResty (gateway) | 8080 | babychain-rpc-proxy |
curl localhost:8080 returns 405 to GET, 200 to POST |
| Gateway indexer | (internal) | babychain-indexer |
logs every 1.5s |
| Gateway read API | 3000 | babychain-api |
curl localhost:3000/health |
| Postgres | 5432 | babychain-postgres |
pg_isready |
| Pay API | 4000 | pay-api |
curl localhost:4000/health |
| Pay settlement | (internal) | pay-settlement |
logs "loop" every 1.5s |
| Pay webhooks | (internal) | pay-webhooks |
logs "dispatcher" every 30s |
| Pay sweep | (internal) | pay-sweep |
logs "sweep loop" every 30s |
| Blockscout | 4001, 4002 | blockscout-frontend, blockscout-backend |
visit localhost:4001 |
| Prometheus | 9090 | prometheus |
visit localhost:9090 |
| Grafana | 3001 | grafana |
visit localhost:3001 |
Troubleshooting
Chain fails to start with "validator set is empty": your
genesis.json is missing the local validator key. Re-run chain/babychain_local.sh to regenerate the genesis and the validator key together.Gateway returns 502 to every call: the chain container is not up yet, or it bound to a different IP. Check
docker ps and the chain''s logs.Pay cannot reach the chain at
http://host.docker.internal:8545: on Linux Docker, host.docker.internal is not always mapped. Edit pay/.env and set CHAIN_RPC_URL=http://<chain-container-ip>:8545 instead.Want a full clean restart?
docker compose -f <file> down -v removes containers and volumes. Use this when changing secrets in .env.