Skip to content

Commit 7b34e86

Browse files
committed
feat(relayer): docker compose
1 parent 88d9648 commit 7b34e86

File tree

6 files changed

+473
-0
lines changed

6 files changed

+473
-0
lines changed

omni-relayer/.dockerignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
target/
2+
.env
3+
config.toml
4+
nats-data/
5+
redis-data/
6+
.git/

omni-relayer/.example-env

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,6 @@ SOLANA_PRIVATE_KEY=
3434
STARKNET_PRIVATE_KEY=
3535
STARKNET_ACCOUNT_ADDRESS=
3636

37+
# NATS credentials (must match nats.conf or your NATS server config)
3738
BRIDGE_NATS_USERNAME=
3839
BRIDGE_NATS_PASSWORD=

omni-relayer/README.md

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
# Omni Relayer
2+
3+
Off-chain component of [Omni Bridge](https://github.com/near-one/omni-bridge) that relays transfers between NEAR and other networks (Ethereum, Solana, BTC, and more).
4+
5+
## Deployment
6+
7+
Docker Compose is the recommended way to deploy the relayer. It bundles the relayer with NATS (message queue) and Redis (state store), and automatically creates the required JetStream streams.
8+
9+
### 1. Configure secrets
10+
11+
```bash
12+
cp .example-env .env
13+
```
14+
15+
Edit `.env` and fill in your credentials:
16+
17+
| Variable | Required | Description |
18+
|----------|----------|-------------|
19+
| `NEAR_OMNI_ACCOUNT_ID` / `NEAR_OMNI_PRIVATE_KEY` | Yes | NEAR account for signing relay transactions |
20+
| `ETH_PRIVATE_KEY`, `BASE_PRIVATE_KEY`, ... | Per chain | EVM chain private keys (only for chains you enable) |
21+
| `SOLANA_PRIVATE_KEY` | If Solana enabled | Solana keypair (bs58-encoded) |
22+
| `INFURA_API_KEY` | If using Infura | API key for EVM RPC endpoints |
23+
| `MONGODB_USERNAME` / `MONGODB_PASSWORD` / `MONGODB_HOST` | If using bridge indexer | Bridge indexer database credentials |
24+
| `BRIDGE_NATS_USERNAME` / `BRIDGE_NATS_PASSWORD` | Yes | NATS authentication credentials |
25+
26+
### 2. Configure the relayer
27+
28+
```bash
29+
cp example-docker-config.toml config.toml
30+
```
31+
32+
Edit `config.toml`:
33+
- **Enable only the chains you want to relay** — comment out or remove sections for chains you don't support
34+
- **Set your RPC endpoints** — replace Infura URLs with your own providers if preferred
35+
- **Adjust fee settings**`fee_discount` in `[bridge_indexer]` controls how much discount you accept (0-100)
36+
- **Token whitelist** (optional) — restrict to specific tokens via `whitelisted_tokens`
37+
38+
### 3. Set NATS credentials
39+
40+
The included `nats.conf` reads credentials from environment variables passed by docker-compose. Set `BRIDGE_NATS_USERNAME` and `BRIDGE_NATS_PASSWORD` in your `.env` file — these are used for both the NATS server and the relayer connection.
41+
42+
### 4. SSH access for build
43+
44+
The build fetches private GitHub dependencies via SSH. Make sure your SSH agent has a key with access to `github.com/near-one`:
45+
46+
```bash
47+
ssh-add -l # check loaded keys
48+
ssh-add ~/.ssh/id_ed25519 # add if needed
49+
ssh -T git@github.com # verify access
50+
```
51+
52+
### 5. Deploy
53+
54+
```bash
55+
docker compose up -d
56+
```
57+
58+
This starts:
59+
- **NATS** — JetStream message queue
60+
- **nats-init** — creates `OMNI_EVENTS` and `RELAYER` streams (runs once, idempotent)
61+
- **Redis** — state and checkpoint storage
62+
- **relayer** — the omni-relayer process
63+
64+
All services are configured with `restart: unless-stopped` for automatic recovery.
65+
66+
### Verify
67+
68+
```bash
69+
# Check all services are running
70+
docker compose ps
71+
72+
# View relayer logs
73+
docker compose logs -f relayer
74+
75+
# Check NATS streams were created
76+
docker compose logs nats-init
77+
```
78+
79+
### Update
80+
81+
```bash
82+
git pull
83+
docker compose up -d --build
84+
```
85+
86+
## Configuration Reference
87+
88+
The relayer is configured through a TOML file with environment variable substitution at parse time (variables like `INFURA_API_KEY` in RPC URLs are replaced automatically from the environment).
89+
90+
Example configs:
91+
- `example-docker-config.toml` — docker-compose deployment (recommended starting point)
92+
- `example-devnet-config.toml` — devnet/testnet with all chains
93+
- `example-testnet-config.toml` — testnet
94+
- `example-mainnet-config.toml` — mainnet
95+
96+
| Section | Purpose |
97+
|---------|---------|
98+
| `[redis]` | Connection URL and retry settings |
99+
| `[nats]` | Connection URL, consumer names, retry backoff, worker count |
100+
| `[bridge_indexer]` | Bridge API URL, MongoDB, fee discount, token whitelist |
101+
| `[near]` | NEAR RPC, bridge contract IDs, signer credentials |
102+
| `[eth]`, `[base]`, `[arb]`, `[bnb]`, `[pol]` | Per-chain RPC URLs, bridge addresses, finalization settings |
103+
| `[solana]` | Solana RPC, program IDs, discriminators |
104+
| `[btc]`, `[zcash]` | UTXO chain RPC and light client settings |
105+
| `[eth.fee_bumping]` | EVM transaction fee bumping thresholds |
106+
107+
## Architecture
108+
109+
```
110+
Indexers (NEAR / EVM / Solana / MongoDB)
111+
└─► NATS OMNI_EVENTS stream
112+
└─► Bridge Indexer consumer
113+
└─► NATS RELAYER stream
114+
└─► Worker pool (process_events)
115+
└─► OmniConnector SDK ─► destination chain
116+
```
117+
118+
1. **Indexers** watch source chains for bridge events
119+
2. Events flow through NATS JetStream with at-least-once delivery
120+
3. **Workers** validate fees, build proofs, and finalize transfers via the OmniConnector SDK
121+
4. **Fee bumping** monitors pending EVM transactions and resubmits with higher gas when stuck
122+
123+
## Building from Source
124+
125+
If you prefer to run without Docker:
126+
127+
```bash
128+
# Prerequisites: Rust 1.86+, running Redis, running NATS with JetStream
129+
130+
# Create JetStream streams (one-time setup)
131+
nats stream add OMNI_EVENTS --subjects "omni-events.>" --retention limits --storage file --discard old
132+
nats stream add RELAYER --subjects "relayer.tasks.>" --retention limits --storage file --discard old
133+
134+
# Build and run
135+
cp .example-env .env
136+
cp example-devnet-config.toml config.toml
137+
# Edit .env and config.toml
138+
139+
cargo run -- --config config.toml
140+
```

omni-relayer/docker-compose.yml

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
services:
2+
nats:
3+
image: nats:2.11-alpine
4+
command: ["--config", "/etc/nats/nats.conf"]
5+
environment:
6+
- NATS_USER=${BRIDGE_NATS_USERNAME}
7+
- NATS_PASSWORD=${BRIDGE_NATS_PASSWORD}
8+
volumes:
9+
- ./nats.conf:/etc/nats/nats.conf:ro
10+
- nats-data:/data
11+
ports:
12+
- "4222:4222"
13+
- "8222:8222"
14+
restart: unless-stopped
15+
healthcheck:
16+
test: ["CMD", "nats-server", "--signal", "ldm"]
17+
interval: 5s
18+
timeout: 3s
19+
retries: 3
20+
21+
nats-init:
22+
image: natsio/nats-box
23+
depends_on:
24+
nats:
25+
condition: service_healthy
26+
env_file: .env
27+
entrypoint: /bin/sh
28+
command:
29+
- -c
30+
- |
31+
NATS_SERVER="nats://$${BRIDGE_NATS_USERNAME}:$${BRIDGE_NATS_PASSWORD}@nats:4222"
32+
33+
nats -s "$$NATS_SERVER" stream add OMNI_EVENTS \
34+
--subjects "omni-events.>" \
35+
--retention limits \
36+
--storage file \
37+
--replicas 1 \
38+
--discard new \
39+
--max-age 14d \
40+
--max-bytes 1GiB \
41+
--dupe-window 1h \
42+
--deny-delete \
43+
--deny-purge \
44+
--defaults \
45+
|| nats -s "$$NATS_SERVER" stream info OMNI_EVENTS
46+
47+
nats -s "$$NATS_SERVER" stream add RELAYER \
48+
--subjects "relayer.>" \
49+
--retention limits \
50+
--storage file \
51+
--replicas 1 \
52+
--discard new \
53+
--max-age 14d \
54+
--max-bytes 1GiB \
55+
--dupe-window 1h \
56+
--deny-delete \
57+
--deny-purge \
58+
--defaults \
59+
|| nats -s "$$NATS_SERVER" stream info RELAYER
60+
61+
redis:
62+
image: redis:7-alpine
63+
ports:
64+
- "6379:6379"
65+
volumes:
66+
- redis-data:/data
67+
restart: unless-stopped
68+
healthcheck:
69+
test: ["CMD", "redis-cli", "ping"]
70+
interval: 5s
71+
timeout: 3s
72+
retries: 3
73+
74+
relayer:
75+
build:
76+
context: .
77+
dockerfile: Dockerfile
78+
ssh:
79+
- default
80+
env_file: .env
81+
volumes:
82+
- ./config.toml:/app/config.toml:ro
83+
command: ["omni-relayer", "--config", "/app/config.toml"]
84+
restart: unless-stopped
85+
depends_on:
86+
nats-init:
87+
condition: service_completed_successfully
88+
redis:
89+
condition: service_healthy
90+
91+
volumes:
92+
nats-data:
93+
redis-data:

0 commit comments

Comments
 (0)